async await blocking ui wp8 - c#

As far as I know the async await keywords work this way: when an await keyword is encountered by the compiler, it suspends the execution of the async function to the caller (in this case the dispatcher), waits for the awaitable function to complete in the background and then then returns back to the function. Am I right?
here is what I am doing:
async private void Button_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
var p = await query("select* from notes", con);
}
and here is the function being called
async Task<List<notes>> query(string sqlstring, SQLiteConnection con)
{
var p = con.Query<notes>(sqlstring);
Thread.Sleep(5000);
MessageBox.Show(p[0].Data);
return p;
}
This blocks the UI thread. why is this happening shouldn't the control be transferred back to the dispatcher when it encounters the await keyword? If so why does the UI get stuck?

Your understanding of await is mostly correct, it's just incomplete. await doesn't suspend execution of the current method immediately. First, the value to be awaited needs to be resolved to a value. Typically you'll have some sort of method that creates a Task. That task will be created synchronously, and then after creating that task, execution of the current method will end, and a continuation will be applied to that task that executes the remainder of the method.
For an async method everything before the first await will be performed synchronously by the caller. It is when the first await (or the end of the method, or an exception that isn't caught by the method) that causes the method to return an actual Task.
Your query method should be able to create the Task that represents the completion of the operation very quickly and then return, so that the caller can await that Task. But it doesn't, it spends over 5 seconds creating the task that represents when it will finish, and when it ends up giving that task to its caller that Task has already finished.
This means that Button_Tap can't yield to its caller (which is the UI's message loop) until after query has finished its 5 seconds of task creation.
All of this means that for Button_Tap to be asynchronous query needs to be asynchronous, and not asynchronous in that it uses the async keyword, but asynchronous in the sense that the method returns almost immediately when called, and that it performs its work after yielding control back to the caller.
As to how to make the method asynchronous, that'll depend. For IO, such as querying a database, what you really want is to have the query provider itself provide inherently asynchronous support. You want to have a query method that returns a Task that you can await, rather than synchronously returning its results. If you have no other choice, then as a last resort you can use Task.Run to perform the query in a non-UI thread and then await that.
As for the Thread.Sleep, that is also synchronously blocking the thread. You need to asynchronously do something after a set period of time instead (if you really do need the delay). You can use Task.Delay for that.
async Task<List<notes>> query(string sqlstring, SQLiteConnection con)
{
var p = await con.QueryAsync<notes>(sqlstring);
//Or, if there is no asynchronous query method
//var p = await Task.Run(() => con.Query<notes>(sqlstring));
await Task.Delay(5000);
MessageBox.Show(p[0].Data);
return p;
}
On a side note, you really shouldn't be trying to re-use your database connections like this. They aren't designed to be used concurrently, for starters. Really they're inherently designed to perform just a single operation. You should be creating your connection right when you need it, and cleaning it up as soon as that one operation has been performed.

Related

Use ConfigureAwait(false) or Task.Run to avoid blocking UI Thread

I'm trying to find out which approach is better let's say we have a button, after user clicks it we perform 1. Send a async request using httpClient
2. Some heavy synchronous staff like computations and saving data to a database.
Like that:
button1.Click += async(sender, e) =>
{
bool a = await Task.Run(async () => { return await MyTask1();});
}
async Task<bool> MyTask1()
{
await new HttpClient().GetAsync("https://www.webpage.com");
DoHeavyStuffFor5minutes();
return true;
}
button2.Click += async(sender, e) =>
{
bool a = await MyTask2();
}
async Task<bool> MyTask2()
{
await new HttpClient().GetAsync("https://www.webpage.com").ConfigureAwait(false);
DoHeavyStuffFor5minutes();
}
From what i understand GetAsync does not block my UI thread because underneath it uses a method which make it runs on different thread perhaps Task.Run or any other method that allows that.
But DoHeavyStuffFor5Minutes will block my UI because it will get called on the caller SynchornizationContext.
So i read that using ConfigureAwait(false) will make code after GetAsync do not run on the same SynchornizationContext as the caller. My question is, which approach is better first or the second one?
There is no need to execute HttpClient.GetAsync on a background thread using Task.Run since the HTTP request is truly asynchronous by nature so in this case your second approach is better that the first one.
When the Task returned by GetAsync has eventually finished, the remainder or MyTask2() will be executed on a thread pool thread assuming you opt out of capturing the context by calling ConfigureAwait(false).
Note however that ConfigureAwait(false) does not guarantee that the callback or remainer won't be run in the original context in all cases.
From Stephen Toub's blog post:
Does ConfigureAwait(false) guarantee the callback won’t be run in the original context?
"No. It guarantees it won’t be queued back to the original contex...but that doesn’t mean the code after an await task.ConfigureAwait(false) won’t still run in the original context. That’s because awaits on already-completed awaitables just keep running past the await synchronously rather than forcing anything to be queued back. So, if you await a task that’s already completed by the time it’s awaited, regardless of whether you used ConfigureAwait(false), the code immediately after this will continue to execute on the current thread in whatever context is still current."
So you might want to off-load DoHeavysTuffFor5minutes, which I assume is a CPU-bound and potentially long-running operation, to a background thread using Task.Run to be on the safe side. At least in the general case.
Also note that a method that is named *Async and returns a Task or Task<T> might still block the calling thread depending on its implementation. In general, this may be a reason to use your first approach of a calling both methods on a background thread in order to avoid blocking the UI thread. If you however use well-implemented APIs, such as HttpClient, this isn't an issue though.

c#, multiple async task execute [duplicate]

In terms of performance, will these 2 methods run GetAllWidgets() and GetAllFoos() in parallel?
Is there any reason to use one over the other? There seems to be a lot happening behind the scenes with the compiler so I don't find it clear.
============= MethodA: Using multiple awaits ======================
public async Task<IHttpActionResult> MethodA()
{
var customer = new Customer();
customer.Widgets = await _widgetService.GetAllWidgets();
customer.Foos = await _fooService.GetAllFoos();
return Ok(customer);
}
=============== MethodB: Using Task.WaitAll =====================
public async Task<IHttpActionResult> MethodB()
{
var customer = new Customer();
var getAllWidgetsTask = _widgetService.GetAllWidgets();
var getAllFoosTask = _fooService.GetAllFos();
Task.WaitAll(new List[] {getAllWidgetsTask, getAllFoosTask});
customer.Widgets = getAllWidgetsTask.Result;
customer.Foos = getAllFoosTask.Result;
return Ok(customer);
}
=====================================
The first option will not execute the two operations concurrently. It will execute the first and await its completion, and only then the second.
The second option will execute both concurrently but will wait for them synchronously (i.e. while blocking a thread).
You shouldn't use both options since the first completes slower than the second and the second blocks a thread without need.
You should wait for both operations asynchronously with Task.WhenAll:
public async Task<IHttpActionResult> MethodB()
{
var customer = new Customer();
var getAllWidgetsTask = _widgetService.GetAllWidgets();
var getAllFoosTask = _fooService.GetAllFos();
await Task.WhenAll(getAllWidgetsTask, getAllFoosTask);
customer.Widgets = await getAllWidgetsTask;
customer.Foos = await getAllFoosTask;
return Ok(customer);
}
Note that after Task.WhenAll completed both tasks already completed so awaiting them completes immediately.
Short answer: No.
Task.WaitAll is blocking, await returns the task as soon as it is encountered and registers the remaining part of the function and continuation.
The "bulk" waiting method you were looking for is Task.WhenAll that actually creates a new Task that finishes when all tasks that were handed to the function are done.
Like so: await Task.WhenAll({getAllWidgetsTask, getAllFoosTask});
That is for the blocking matter.
Also your first function does not execute both functions parallel. To get this working with await you'd have to write something like this:
var widgetsTask = _widgetService.GetAllWidgets();
var foosTask = _fooService.GetAllWidgets();
customer.Widgets = await widgetsTask;
customer.Foos = await foosTask;
This will make the first example to act very similar to the Task.WhenAll method.
As an addition to what #i3arnon said. You will see that when you use await you are forced to have to declare the enclosing method as async, but with waitAll you don't. That should tell you that there is more to it than what the main answer says. Here it is:
WaitAll will block until the given tasks finish, it does not pass control back to the caller while those tasks are running. Also as mentioned, the tasks are run asynchronous to themselves, not to the caller.
Await will not block the caller thread, it will however suspend the execution of the code below it, but while the task is running, control is returned back to the caller. For the fact that control is returned back to the caller (the called method is running async), you have to mark the method as async.
Hopefully the difference is clear. Cheers
Only your second option will run them in parallel. Your first will wait on each call in sequence.
As soon as you invoke the async method it will start executing. Whether it will execute on the current thread (and thus run synchronously) or it will run async is not possible to determine.
Thus, in your first example the first method will start doing work, but then you artificially stops the flow of the code with the await. And thus the second method will not be invoked before the first is done executing.
The second example invokes both methods without stopping the flow with an await. Thus they will potentially run in parallel if the methods are asynchronous.

Execute many long-running tasks with the "TAP" design pattern

I'm currently developing a system where I'll need to connect a couple of clients to a server, which means that I will need to run a background task for each client. The last project I built was with APM, but I am now trying out to build everything around the new and better TAP.
My question is, how do I run many long-running asynchronous functions within a synchronous function? I know that I could use Task.Run(), but it feels like there's a better way. If I just try to run the function as it is, the warning ...
"Because this call is not awaited, execution of the current method continues before the call is completed."
... appears, which means that I'm doing something wrong.. or do I? What is the most efficient and correct way to make all of the clients run at the same time?
class AsyncClient
{
public AsyncClient()
{
...
}
public async Task RunAsync(IPAddress address, int port)
{
... waiting for data
}
}
static void Main(string[] args)
{
List<AsyncClient> clients = new <AsyncClient>();
clients.Add(new AsyncClient());
clients.Add(new AsyncClient());
clients.Add(new AsyncClient());
foreach (var c in clients)
{
// What is the best way to start every async tasks?
c.RunAsync("127.0.0.1", "8080");
// ^ This gives the warning "Because this call is not awaited,
// execution of the current method continues before the call is completed."
}
}
Thanks!
First you should change your Main method to be async:
static async Task Main(string[] args)
Then you can await the asynchronous operations.
To allow them to run in parallel, you can make use of LINQ Select:
IEnumerable<Task> tasks = clients.Select(c => c.RunAsync("127.0.0.1", "8080"));
await Task.WhenAll(tasks);
Task.WhenAll returns a new Task that completes when all the provided Tasks have completed.
Without awaiting the Tasks, there is a good chance that your Main method will complete, and hence the program will exit, before the Tasks have competed,
So you have a non async method, and in this non-async method you want to call async methods.
Usually a method is async, because somewhere deep inside your thread has to wait for another lengthy process to finish. Think of a file to be written, a database query to be executed, or some information to be fetched from the internet. Those are typically functions where you'll find async methods next to the non-async methods.
Instead of waiting idly for the other process to finish its task, the caller of the method receives control to do other things, until it sees an await. Control is given to the caller until it sees an await etc.
So if you want to do other things while the other process is executing its task: simply don't await. The problem is of course: you want to know the result of the other task, before your function exits. If you don't if will be hard to define the post condition of your method.
void MyMethod()
{
Task<int> taskA = MethodAasync(...);
// you didn't await, you are free to do something else, like calling another async method
Task<double> taskB = MethodBasync(...);
DoSomethingUseful();
// if here, you need the result of taskA. Wait until it is ready
// this blocks your thread!
taskA.Wait();
int resultA = taskA.Result();
ProcessResult(resultA);
// if desired, you can wait for a collection of tasks:
Task[] tasksToWaitFor = new Task[] {taskA, taskB};
Task.WaitAll(tasksToWaitFor);
int resultA = taskA.Result();
double resultB = taskB.Result();
ProcessResults(resultA, resultB);
}
Even if you are not interested in the result of the tasks, it is wise to wait for them to finish. This allows you to react on exceptions.
By the way, did you see that I did not call Task.Run! What happens, is that my thread enters MethodAasync until it sees an await. Then the procedure gets back control, so it enters MethodBasync until is sees an await. Your procedure gets back control to DoSomethingUseful.
As soon as the other process (database query, write file, etc) is finished, one of the threads of the thread pool continues processing the statements after the await, until it meets a new await, or until there is nothing more to process.
Task.Wait and Task.WaitAll are the methods that stop this asynchronousness: the thread will really block until all async methods are completely finished.
There is seldom a reason to use Task.Run if you want to call an async method: simply call it, do not wait for it, so you can do other useful stuff. Make sure you Wait for the task to finish as soon as you need the result, or at the latest when you return the method.
Another method would be to return the tasks without waiting for them to finish, to give your caller the opportunity to do something useful as long as the tasks are not completed. Of course this can only be done if your procedure doesn't need the result of the task. It also obliges your caller to wait for completion, or pass the tasks to his caller.
The only reason to Task.Run that I can see, is that you want to start a lengthy procedure within your own process, that you don't want to wait for right now. Think of doing a lengthy calculations. Don't use Task.Run if another process is involved. In that case the other process should have an async function, or you should create an async extension method that does the task.Run.
int DoSomeLengthyCalculations(...) {...};
async Task<MyResult> CalculateIt(...)
{
Task<int> taskLengthyCalculations = Task.Run( () => DoSomeLengthyCalculations(...);
// if desired DoSomethingUsefull; after that wait for the task to end
// and process the result:
Task.Wait(taskLengthyCalculations);
int resultLengthyCalculations = taskLengthyCalucalations.Result();
MyResult result = ProcessResult(resultLengthyCalculations);
return result;
}
The nice thing is that you've hidden whether you are doing the lengthy calculations, or that someone else is doing it. For instance if you are unit testing methods that async access a database, you can mock this while accessing a Dictionary instead.
}

C# Understanding trouble with blocked UI and async / await vs. Task.Run?

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 :-}

.NET async\await fundamentals

After playing with .NET 4.5 async\await framework I have a question.
Let's look at this program (the msdn example):
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
DoIndependentWork();
string urlContents = await getStringTask;
return urlContents.Length;
}
void DoIndependentWork()
{
resultsTextBox.Text += "Working . . . . . . .\r\n";
}
The program will run in this order:
new HttpClient.
GetStringAsync invoke synchronously.
In some point, GetStringAsync calls await and the control return to AccessTheWebAsync.
DoIndependentWork invoked.
The program waits the string to be returned (blocks if the operation didn't complete).
return the length of the urlContent.
One thing that took me a while to understand is that the method GetStringAsync runs synchronously despite its name (the name convention is really misleading).
In oreder to run the method asynchronously, we need to use Task.Run or Task.Factory.StartNew explicitly.
But the real question is, if we have independent work, why not do it right away rather then waiting the await to be called from GetStringAsync? (In other words, why async methods doesn't run asynchronously by definition?)
EDIT:
I'll rephrase the second and third operations:
(2) GetStringAsync start synchronously.
(3) In some point, GetStringAsync calls await and the thread forks, the control return to AccessTheWebAsync.
One thing that took me a while to understand is that the method GetStringAsync runs synchronously despite its name (the name convention is really misleading).
That is incorrect. GetStringAsync returns a Task<string>. It will return immediately, which means DoIndependentWork will (potentially) run before the download has completed. The await operator will asynchronously wait until the Task<T> returned by GetStringAsync is done.
But the real question is, if we have independent work, why not do it right away rather then waiting the await to be called from GetStringAsync? (In other words, why async methods doesn't run asynchronously by definition?)
The actual "work" of the asynchronous methods is running after the method has returned. The Task that's returned will (normally) be in a state that's not completed, which means the method is still running asynchronously. You can check Task.IsCompleted to verify.
Try this:
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
Debug.WriteLine("Completed? {0}", getStringTask.IsCompleted); // Will likely print false
DoIndependentWork();
string urlContents = await getStringTask;
Debug.WriteLine("Completed now? {0}", getStringTask.IsCompleted); // Will always print true
Each async method is split into segments on each await. Each segment will become a state on a compiler generated state machine.
Each await instruction works on an awaitable for which a Task is the most common case.
Each state/segment will be executed synchronously until the where the received awaitable is checked if it is already completed.
If the awaitable is completed, it execution will continue on the next state.
If the awaitable is not completed and there isn't a current SynchronizationContext, the execution will be blocked until the the awaitable is completed at which time the execution of the next state will be started.
If a current SynchronizationContext exists, the execution will return to the caller and when the awaitable is completed the continuation to the next state will be posted to the captured SynchronizationContext.
The program waits the string to be returned (blocks if the operation
didn't complete).
await doesn't block on await getStringTask. It will save the internal state of the AccessTheWebAsync method (local variables and where the execution point is) in a compiler-generated state machine object and will return to the outer method which called AccessTheWebAsync. The state will be restored and the execution will be resumed later asynchronously when getStringTask task has become completed, via a compiler-generated continuation callback. If you're familiar with C# iterators and yield keyword, the await state machine control flow is very similar to it, albeit iterators are executed synchronously.
How exactly the execution will be resumed after await depends on the synchronization context of the thread initiating the await. If it's a UI thread pumping Windows messages, the continuation callback will likely be called on the next iteration of the thread's message loop (typically inside Application.Run). If it's a non-UI thread (e.g., a console application), the continuation may happen on a different thread at all. So, while the control flow of your method remains logically linear, technically it is not (as it would have been if you just did getStringTask.Wait() instead of await getStringTask).
The program waits the string to be returned (blocks if the operation didn't complete).
No, it doesn't. await waits, but it doesn't block any threads. That's the whole point.
One thing that took me a while to understand is that the method GetStringAsync runs synchronously despite its name (the name convention is really misleading).
That's wrong. Most of the method does run asynchronously. It most likely also has a small synchronous part at the start, but that should be negligible.
In oreder to run the method asynchronously, we need to use Task.Run or Task.Factory.StartNew explicitly.
No, the method already does run asynchronously. If you want to run the small synchronous part on another thread, then you can use Task.Run(), but that almost never makes any sense. Also, don't use StartNew() for this, it doesn't work well with async methods.
In other words, why async methods doesn't run asynchronously by definition?
A significant point about await is that it resumes on the same context where it left.
This can be very useful in GUI applications, where you often want to modify the UI, then execute the async operation and then modify the UI again. If async automatically meant that the whole method executes on a ThreadPool thread, then that wouldn't be possible.
Also, doing it this way is more efficient, because you don't have to switch to another thread for something that takes very little time.

Categories