Ths situtation:
I get from different internet locations, json objects.
These containsmany Geocoordinates that I put onto a BingMap.
That works perfect very well.
The Problem:
but when I fetch the data from the internet locations I get a blocking ui.
Is there a method to run that in background?
I tried the async functionality but I get there a blocking UI too..
Here some code
Caller
public async void Caller_Click(){
await jsonDataClass.DoOperations();
}
The method in the jsonDataClass
public async Task<bool> DoOperations(){
// do requests and some stuff..
var fetchedElements = getdata(); // not async, because its in a portable lib
foreach (var element in fetchedElements)
OnEvent(element); // raises an event to assing the element to the Bing map
}
Don't ignore compiler warnings. In particular, if you have an async method that doesn't use await, then the compiler will specifically tell you that the method is not asynchronous and will run synchronously.
The first thing I would recommend is to change getdata so that it is async. The Microsoft.Bcl.Async NuGet package extends async support to portable class libraries.
If that's not possible, then you'll have to execute getdata on a background thread, like this:
public async Task<bool> DoOperations()
{
var fetchedElements = await Task.Run(() => getdata());
foreach (var element in fetchedElements)
OnEvent(element);
}
P.S. The term "background task" has a special meaning in WinRT. What you actually need is to run code on a thread pool thread (or background thread), which is different than what WinRT calls a "background task".
Related
I'm trying to refactor an existing synchronous app into one that uses Async/Await. This WPF app was written originally using a BackgroundWorker thread calling a bunch of synchronous methods. I went down to the deepest level and worked my way up, converting these methods to async, using await Task.Run(()..) on some of them that didn't seem to be taking too long.
I am stuck on something though. I want to pass in an IProgress parameter, to be able to get feedback into the UI -- and the last, deepest method, the one that takes the longest to execute, is written this way:
public static Task<bool> SaveToFileAsync(string filePath)
{
return Task.Run(() => SaveToFile(filePath));
/*
SaveToFile calls into an unmanaged dll that uses a few loops and writes
to file using fopen/fwrite...
*/
}
private async void CreateObjectAndSaveToFile(/*IProgress progress*/)
{
List<Task> SaveFileTaskArray = new List<Task>();
int index = 0;
foreach (...)
{
//
{
DoSomethingThatTakesSomeTime();
//Start Async Task to save this SomeThing to file
SaveFileTaskArray.Add(SaveToFileAsync(fileName));
}
index++;
}
await Task.WhenAll(SaveFileTaskArray);
}
Now if I call CreateObjectAndSaveToFile() on the UI side like so:
await CreateObjectAndSaveToFile();
I get the desired effect - UI is responsive and files get saved one by one (can be 10-20 files). But for completeness, I'd like to add a progress bar to this (and therefore adding that IProgress parameter all the way down).
I'm not sure how I can do that.
You mention in the comments that you know how to use IProgress already. So if you want report progress as each task finishes, you can use WhenAny() instead of WhenAll(), and remove each task from the list as it finishes. Something like this:
while (SaveFileTaskArray.Count > 0) {
var finishedTask = await Task.WhenAny(SaveFileTaskArray);
SaveFileTaskArray.Remove(finishedTask);
//Report progress of how many are left
progress.Report(SaveFileTaskArray.Count);
}
The Microsoft documentation actually has a whole article about this, if you want to read more: Start Multiple Async Tasks and Process Them As They Complete
I have a constructor that is called on UI thread in my WPF app. Inside of it, it calls async method but it must be done in a synchronous way. So I tried to call wait, but it caused deadlock an I understand why. So I introduced argument that indicates if method should be run in a asynchronous or synchronous manner. Something like this:
// constructor that is called on UI thread
public MyClass()
{
Method1(false).Wait();
}
public async Task Method1(bool runAsync)
{
await Method2(runAsync);
}
public async Task Method2(bool runAsync)
{
if (runAsync)
{
await Task.Run(() => Thread.Sleep(1000));
}
else
{
Thread.Sleep(1000);
}
}
I don't want to use ConfigureAwait because I want everything to run on UI thread. Will Method1(false).Wait(); ever cause a deadlock (is it safe to use)? I tested it a lot and it didn't, but I'm not sure. Finally, my real question is: if 'await Task.Run(...' is never executed, is my method completely synchronous? I found several posts on this subject, but none of them answers directly to my question.
I have a constructor that is called on UI thread in my WPF app. Inside of it, it calls async method but it must be done in a synchronous way.
I'm gonna stop you right there. The best solution is not to run synchronous/blocking code on the UI thread. That degrades your user experience. Instead, you should restructure your code so that you're never in this situation in the first place.
When a UI is being shown, the UI framework asks your code for the data to display. Your code should run synchronously and return immediately (not blocking). But your code also needs to do some asynchronous work in order to have the data to display. So there's a conflict there.
The solution is to design an intermediate state for your UI, e.g., a "loading..." message or a spinner. Then, when your code starts, it can synchronously/immediately display the "loading" state (and start the asynchronous operation), and when the asynchronous data arrives, the code updates the UI to the "final" state.
I discuss this pattern in more detail in my article on async MVVM data.
Instead of wrestling with async stuff at construction (your blocking solution isn't so good), why not write an async factory to spew out these objects?
class MyClass
{
public MyClass()
{
}
public async Task Method2(bool runAsync)
{
//async immediately
await Task.Delay(1000); //no Thread.Sleep. Blocking code != good
}
}
then
public MyClassFactory
{
public async Task<MyClass> GetAsync()
{
var c = new MyClass();
await c.Method2();
return c;
}
}
I'm trying to do some asynchronous I/O work detached from UI thread. Somewhere I read:
1) For CPU-bound code, you await an operation which is started on a
background thread with the Task.Run method. Such as calculating prime
numbers
2) For I/O-bound code, you await an operation which returns a
Task or Task inside of an async method. Such as waiting for
network or database
So I did this:
// in windows form UI
private async void btnImport_Click(object sender, EventArgs e) {
// [...]
List<DataRow> rows = await importer.ImportDataAsync(123, 456);
// [...]
}
// in Importer.ImportDataAsync:
public async Task<List<DataRow>> ImportDataAsync(int parent, int child, CancellationToken token = default(CancellationToken)) {
// [...]
List<DataRow> list = await RealImportFromDB(parent, child);
return list;
// [...]
}
public List<DataRow> RealImportFromDB(int p, int c) {
List<DataRow> rowList;
// here fetch the rows from DB over slow network
// and return the row list
return rowList;
}
With this approach the UI is blocked.
If I call RealImportFromDB(...) like this
List<DataRow> l = await Task.Run(() => RealImportFromDB(parent, child));
the UI is not blocked but that conflicts with point 2) from above IMHO.
Where do I do things wrong?
Best regards, alex
public List<DataRow> RealImportFromDB(int p, int c) is a blocking call to the database, so to execute it Asynchronously, you have used the #1, where you have wrapped the call inside the Task.Run, which will free up Ui thread as expected
With this approach the UI is blocked. If I call RealImportFromDB(...)
It is since the method is not meant for the Asynchronous calling, it doesn't return a Task or Task<T>, which is the common requirement to make the Async call
Your code, await RealImportFromDB(parent, child) is not correct that's a compilation error, since you can only await the calls, which implements the GetAwaiter()internally check (this and this) and most common scenario is to return Task or Task<T>, there are other types too
Let's try to understand your two statements:
1) For CPU-bound code, you await an operation which is started on a background thread with the Task.Run method. Such as calculating prime numbers
This is what you are currently doing and is often done in clients to free up Ui thread, while processing takes place in background, but this would still use a Thread pool thread to do the execution, which is not as important as Ui thread, but still system resource
2) For I/O-bound code, you await an operation which returns a Task or Task inside of an async method. Such as waiting for network or database
To implement this you need a method, which is Async by default and returning a Task or Task<T>, such methods are part of all data frameworks, for every sync method nowadays there's a corresponding async method to initiate a asynchronous execution and they are the true IO calls, where they don't use a thread, since the processing is not in the same process, its across network / process boundary, so calling thread needn't wait, it just needs to come back and pick the result, when it arrives (any thread pool thread, not necessary the dispatching thread). Internally such methods use TaskCompletionSource<T> (When to use TaskCompletionSource), which has mechanism to notify the caller when the network call has accomplished
To implement this you need a method, which is Async by default and
returning a Task or Task
Thanks a lot, this was my trouble. My RealImportFromDB(...) method is not an async method since it deals with an older, proprietary library that seems not ready for async calls.
Those were my thougths:
with awaiting the result from ImportDataAsync(...) everything that is called within (e.g. RealImportFromDB(...)) is dispatched from the UI thread also. So to say: everything within ImportDataAsync(...) is encapsulated / runs on in the second, non-blocking thread.
#others: yes you are right, the sample from my code won't even compile. Fiddled around a lot, so the code sample does not show everything what was changed, sorry for that :-}
I’m using MvvmCross and the AsyncEx library within a Windows 10 (UWP) App.
In a ViewModel, I have an INotifyTaskCompletion property (1) which is wired-up to an Async method in the ViewModel (2)
In (2), I call an Async library method which:
Checks a local cache
Downloads data asynchronously
Adds the data to the cache
The caching code cannot be made asynchronous and so the library method contains both blocking and asynchronous code.
Q. What’s the best way to prevent blocking the UI thread?
I understand from Stephen Cleary to not to block in asynchronous code and not use Task.Run in library methods. So do I have to….
Move the caching calls into (2) e.g.
Use Task.Run (to check the cache)
Call the library method asynchronously
Use Task.Run again (to cache the data)?
Is there a better way?
If you have completely synchronous code which you can't change to make it return an awaitable, and want to make it asynchronous, then yes, your only choice if you want to use async/await is to use Task.Run().
Something like:
public async Task<T> MyMethod()
{
T result = await Task.Run(() => CheckCacheOnSyncMethodICantChange());
if(result != null)
{
result = await MyLibraryMethodThatReturnsATask();
await Task.Run(() => AddToCacheOnSyncMethodICantChange(result));
}
return result;
}
Should be ok.
public MainPage()
{
Method_1();
Method_2();
Method_3();
Method_4();
Method_5();
Method_6();
}
I am writing a Windows Phone 8.1 App (WINRT XAML). How to make these methods execute at a time from constructor? What I mean to ask is about multithreading, i want these methods to get executed sidebyside and not one after another.
Does this effect loading of application? will app load fast/slow?
First off, you don't want to execute those methods in the constructor if they are long running methods. Wait until the page is loaded:
private async void Page_Loaded(object sender, RoutedEventArgs e)
{
Task m1task = Method_1();
Task m2task = Method_2();
Task m3task = Method_3();
Task all = Task.WhenAll(m1Task, m2Task, m3Task);
await all;
}
The code will load off these operations to another thread and as long as your methods are properly implemented your UI will stay responsive (so don't use wait() for instance).
This is what a sample method could look like:
private async Task Method_1() {
// Long running operation goes here
}
If you have some heavy computations to do, wrap them into Task.Run(() => { // Code });It's really essential that you're aware of the concepts of asynchronous programming. You might want to read on here:
Do you have to put Task.Run in a method to make it async?
await vs Task.Wait - Deadlock?
When correctly use Task.Run and when just async-await
But seriously, you're writing that your methods are not UI related. You might be better off running those somewhere else (e.g. in your ViewModels or even in a background task / service).
Mark the methods as Async with return type Task.
eg. public async Task method1(){}
You won't be able to fire any UI activities from them, but they'll run outside of the main thread.