c#, multiple async task execute [duplicate] - c#

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.

Related

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

Understanding acync and await in C#

I'm learning async and await operation in c#. I couldn't understand the flow of execution when it handles multiple async operation. for eg: I have the below code in my c# application.
await repository.GetAsync(values); // execute for 10 sec
var result = repository.setAsync(data); // 20 sec
dataresult = await repository.GetAsync(result); //execute for 10 sec
I have three async calls here.
As per my understanding each call will have a callback and this will not wait for one action to complete.
So how I can ensure the action is complete?
The repository.setAsync will execute before repository.GetAsync(values) complete its execution? or this will execute only after repository.GetAsync(values) execution completed?
So what will be the order of execution?
1)
await repository.GetAsync(values); // started await method execution, since there is no callback it will not set and will start execute the next before complete this.
var result = repository.setAsync(data); // will execute for 20 sec. Once completed will go to previous thread and complete that.
await repository.GetAsync(values); // started await method execution, complete it and move to the next line.
var result = repository.setAsync(data); // will execute for 20 sec.
When you execute something synchronously, you wait for it to finish before moving on to another task. When you execute something asynchronously, you can move on to another task before it finishes. But here, for asynchronous it waiting for the operation to finish. Why this contradiction?
I want to return the dataresult only once the operation has been completed.
I feel this is contrary to fire and forget. Whether these two are same or different concepts?
As per the below link reference
The await keyword does not block the thread until the task is
complete.
But from the answers posted here, I understood this will pause the execution. which is true? Am I missed something?
As per my understanding each call will have a callback and this will not wait for one action to complete.
When you use await, the code will wait for the action to complete before moving on. This is the way you deal with data dependencies -- situations when a task needs results from a previous task to be available before it can start processing. The only action that is not awaited is result, so GetAsync(result) must take Task<T> as its parameter, where T is the type of whatever SetAsync method returns.
Note
If code following the await does not need to be executed on the UI thread you should call ConfigureAwait(false) upon the Task you are awaiting. Why is this best practice? Stephen Cleary provides an excellent blog post on the topic of async/await deadlocks that explains it.
It is also very likely that you are missing await on the second line and an assignment of data on the first line:
var data = await repository.GetAsync(values).ConfigureAwait(false);
var result = await repository.SetAsync(data).ConfigureAwait(false);
dataresult = await repository.GetAsync(result).ConfigureAwait(false);
So what is the concept of callback and fire and forget here?
If callback happens before the call of await, which is possible when you fire up a task, do something else, and then await that task, you get a chance to do more work in between "firing and forgetting" and getting the results back. The key here is that there must be no data dependency in the middle:
var dataTask = repository.GetAsyncOne(values); // Fire and forget
// Do something else in the middle
var result = await repository.SetAsync(data).ConfigureAwait(false);
// If the task has completed, there will be no wait
var data = await dataTask.ConfigureAwait(false);

Async/Await VS Task.Run : When to use ? How to use?

Okay I hope I got the basics of async/await but still some questions a re lingering in my head.
But now it is the problem I am talking about . Suppose in this simple example
static void Main(string[] args)
{
Method();
Console.WriteLine("Main Thread");
Console.ReadLine();
}
public async static void Method()
{
await Task.Run(new Action(LongTask));
Console.WriteLine("New Thread");
}
public static void LongTask()
{
Thread.Sleep(8000);
Console.WriteLine("Long Task");
}
The main thread still continues and prints Main Thread after calling Method() and encountering an await for 8 seconds .
So accordingly the Method() returns to the caller i.e. to the main function here once it encounters await , saves the synch context and keeps on executing from there .
It prints Main Thread first .
Then after 8 seconds complete , Long Task and then New Thread get printed.
This part I got . My question is in my application :
public IList<createcaseoutput> createCase(CreateCaseInput CreateCaseInput,SaveCaseSearchInput SaveCaseSearchInput)
{
.............
SQL.CaseSQL.getCreateCaseParameters(CreateCaseInput, out strSPQuery, out listParam);
var AcctLst = rep.ExecuteStoredProcedure<createcaseoutput>(strSPQuery, listParam).ToList();
if (!string.IsNullOrEmpty(AcctLst.ElementAt(0).o_case_seq.ToString()))
{
await saveCaseSearch(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
}
console.writeline("Async called");
return AcctLst;
}
public async Task<ilist<savecasesearchoutput>> saveCaseSearch(SaveCaseSearchInput SaveCaseSearchInput,Int64? case_key)
{
..........................
SQL.CaseSQL.getSaveCaseSearchParameters(SaveCaseSearchInput, case_key, out strSPQuery, out listParam);
var AcctLst = await rep.ExecuteStoredProcedureAsync<entities.case.savecasesearchoutput>(strSPQuery, listParam);
return AcctLst;
}
Here also createCase is encountering await and
it should return immediately right and execute the very next line itself and print Async called
before even the SaveCaseSearch completes right ?
Okay if I am thinking loud it might be control returns to the caller .
So is it like if I wrap my call SavCaseSearch inside another async/await method named suppose
async DoWork() {....
}
and call this DoWork() from CreateCase() directly so then
It will go on printing "Async called" once call to DoWork() encounters await and before it even completes ?
Am I thinking in the correct way ?
Also sometimes I see and get confused between
await someAsync()
and
await Task.Run(() => someAsync()) ..
what's the difference between them ? and which one to follow ?
My question is in my application :
Your code won't compile because you're using await without async. Corrected code would be:
public async Task<IList<createcaseoutput>> createCaseAsync(CreateCaseInput CreateCaseInput,SaveCaseSearchInput SaveCaseSearchInput)
{
...
await saveCaseSearch(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
console.writeline("Async called");
return AcctLst;
}
Here also createCase is encountering await and it should return immediately right and execute the very next line itself and print Async called before even the SaveCaseSearch completes right ?
No. This code:
await saveCaseSearch(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
is the same as this code:
var saveTask = saveCaseSearchAsync(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
await saveTask;
So, first, createCaseAsync would call saveCaseSearchAsync. Presumably, saveCaseSearchAsync is performing some asynchronous operation, so it will return an incomplete task to createCaseAsync. createCaseAsync then awaits that task, which causes it to return an incomplete task to its caller.
Eventually, saveCaseSearchAsync will complete, which will complete the task it returned (which I called saveTask in the code above). This in turn will continue executing createCaseAsync, and it will proceed to the next line and print "Async called" on the console.
So is it like if I wrap my call SavCaseSearch inside another async/await method
You wouldn't need a wrapper because createCaseAsync is already returning a Task.
what's the difference between them ? and which one to follow ?
Task.Run is mainly for pushing blocking work off the UI thread and onto the threadpool. Since you're on ASP.NET, don't use Task.Run.
The first rule of async is to always use async or never use async.
If your underlying API can't handle async it's no use to use async in the upper layers (like ASP.NET MVC), since at some point you'll get thread starvation as all threads are occupied waiting on IO operations (like DB calls).
Your example is a classical case where you mix sync and async. The Sleep call will lock the thread until it completes. You should have used Task.Delay instead as it would have released the thread until the delay completes.
My advice to you is to simply start by following the rule I mentioned first and only when IO bound operations like DB or file calls are involved. Then when you understand async better you can start to break it since you then have a much better understanding in what it can lead to.
(Sorry for not answering your questions directly, but threading is a complex topic and your brain can fry if you try to get it all in directly. Start small.)
Here also createCase is encountering await and it should return immediately right and execute the very next line itself and print Async called before even the SaveCaseSearch completes right ?
This shouldn't even compile. The 'await' operator can only be use within an 'async' method. That said, if you remove the 'await' operator, then the next line will print "Async called" before even the saveCaseSearch completes.
Am I thinking in the correct way ?
saveCaseSearch is already an 'async' method, so you don't need to wrap it to achieve the desired result. That said, you could wrap it in another method, if you really want to.
what's the difference between them ? and which one to follow ?
The 'await' operator wait for a Task object so either one is fine. I would chose await someAsync(), because it's less code to write.
Regarding the difference between async/await and Tasks...
Async/Await are syntactic keywords to simplify your code, as everything before the await keyword happens in the calling thread and everything from the await onward happens is in the task's continuation.
Setting this up with tasks using the TPL will require a lot of code and readability suffers. Note however, Underneath it is still using Tasks and Continuations.
Further, they cannot always be used in place of Tasks like when the completion of Task is nondeterministic, or if you have multiple levels of Tasks along with the usage of TaskCompletionSource.
For more information read the chapter 4 "Asynchronous Programming" in the book "Writing High-Performance .NET Code" by Ben Watson
Note also, Internally, the TPL uses the .NET thread pool, but does so more intelligently, by executing multiple Tasks on the same thread sequentially before returning the thread back to the pool. It can do this via intelligent use of delegate objects.

Why is this code running synchronously?

I am trying to understand concurrency by doing it in code. I have a code snippet which I thought was running asynchronously. But when I put the debug writeline statements in, I found that it is running synchronously. Can someone explain what I need to do differently to push ComputeBB() onto another thread using Task.Something?
Clarification I want this code to run ComputeBB in some other thread so that the main thread will keep on running without blocking.
Here is the code:
{
// part of the calling method
Debug.WriteLine("About to call ComputeBB");
returnDTM.myBoundingBox = await Task.Run(() => returnDTM.ComputeBB());
Debug.WriteLine("Just called await ComputBB.");
return returnDTM;
}
private ptsBoundingBox2d ComputeBB()
{
Debug.WriteLine("Starting ComputeBB.");
Stopwatch sw = new Stopwatch(); sw.Start();
var point1 = this.allPoints.FirstOrDefault().Value;
var returnBB = new ptsBoundingBox2d(
point1.x, point1.y, point1.z, point1.x, point1.y, point1.z);
Parallel.ForEach(this.allPoints,
p => returnBB.expandByPoint(p.Value.x, p.Value.y, p.Value.z)
);
sw.Stop();
Debug.WriteLine(String.Format("Compute BB took {0}", sw.Elapsed));
return returnBB;
}
Here is the output in the immediate window:
About to call ComputeBB
Starting ComputeBB.
Compute BB took 00:00:00.1790574
Just called await ComputBB.
Clarification If it were really running asynchronously it would be in this order:
About to call ComputeBB
Just called await ComputBB.
Starting ComputeBB.
Compute BB took 00:00:00.1790574
But it is not.
Elaboration
The calling code has signature like so: private static async Task loadAsBinaryAsync(string fileName) At the next level up, though, I attempt to stop using async. So here is the call stack from top to bottom:
static void Main(string[] args)
{
aTinFile = ptsDTM.CreateFromExistingFile("TestSave.ptsTin");
// more stuff
}
public static ptsDTM CreateFromExistingFile(string fileName)
{
ptsDTM returnTin = new ptsDTM();
Task<ptsDTM> tsk = Task.Run(() => loadAsBinaryAsync(fileName));
returnTin = tsk.Result; // I suspect the problem is here.
return retunTin;
}
private static async Task<ptsDTM> loadAsBinaryAsync(string fileName)
{
// do a lot of processing
Debug.WriteLine("About to call ComputeBB");
returnDTM.myBoundingBox = await Task.Run(() => returnDTM.ComputeBB());
Debug.WriteLine("Just called await ComputBB.");
return returnDTM;
}
I have a code snippet which I thought was running asynchronously. But when I put the debug writeline statements in, I found that it is running synchronously.
await is used to asynchronously wait an operations completion. While doing so, it yields control back to the calling method until it's completion.
what I need to do differently to push ComputeBB() onto another thread
It is already ran on a thread pool thread. If you don't want to asynchronously wait on it in a "fire and forget" fashion, don't await the expression. Note this will have an effect on exception handling. Any exception which occurs inside the provided delegate would be captured inside the given Task, if you don't await, there is a chance they will go about unhandled.
Edit:
Lets look at this piece of code:
public static ptsDTM CreateFromExistingFile(string fileName)
{
ptsDTM returnTin = new ptsDTM();
Task<ptsDTM> tsk = Task.Run(() => loadAsBinaryAsync(fileName));
returnTin = tsk.Result; // I suspect the problem is here.
return retunTin;
}
What you're currently doing is synchronously blocking when you use tsk.Result. Also, for some reason you're calling Task.Run twice, once in each method. That is unnecessary. If you want to return your ptsDTM instance from CreateFromExistingFile, you will have to await it, there is no getting around that. "Fire and Forget" execution doesn't care about the result, at all. It simply wants to start whichever operation it needs, if it fails or succeeds is usually a non-concern. That is clearly not the case here.
You'll need to do something like this:
private PtsDtm LoadAsBinary(string fileName)
{
Debug.WriteLine("About to call ComputeBB");
returnDTM.myBoundingBox = returnDTM.ComputeBB();
Debug.WriteLine("Just called ComputeBB.");
return returnDTM;
}
And then somewhere up higher up the call stack, you don't actually need CreateFromExistingFiles, simply call:
Task.Run(() => LoadAsBinary(fileName));
When needed.
Also, please, read the C# naming conventions, which you're currently not following.
await's whole purpose is in adding the synchronicity back in asynchronous code. This allows you to easily partition the parts that are happenning synchronously and asynchronously. Your example is absurd in that it never takes any advantage whatsoever of this - if you just called the method directly instead of wrapping it in Task.Run and awaiting that, you would have had the exact same result (with less overhead).
Consider this, though:
await
Task.WhenAll
(
loadAsBinaryAsync(fileName1),
loadAsBinaryAsync(fileName2),
loadAsBinaryAsync(fileName3)
);
Again, you have the synchronicity back (await functions as the synchronization barrier), but you've actually performed three independent operations asynchronously with respect to each other.
Now, there's no reason to do something like this in your code, since you're using Parallel.ForEach at the bottom level - you're already using the CPU to the max (with unnecessary overhead, but let's ignore that for now).
So the basic usage of await is actually to handle asynchronous I/O rather than CPU work - apart from simplifying code that relies on some parts of CPU work being synchronised and some not (e.g. you have four threads of execution that simultaneously process different parts of the problem, but at some point have to be reunited to make sense of the individual parts - look at the Barrier class, for example). This includes stuff like "making sure the UI doesn't block while some CPU intensive operation happens in the background" - this makes the CPU work asynchronous with respect to the UI. But at some point, you still want to reintroduce the synchronicity, to make sure you can display the results of the work on the UI.
Consider this winforms code snippet:
async void btnDoStuff_Click(object sender, EventArgs e)
{
lblProgress.Text = "Calculating...";
var result = await DoTheUltraHardStuff();
lblProgress.Text = "Done! The result is " + result;
}
(note that the method is async void, not async Task nor async Task<T>)
What happens is that (on the GUI thread) the label is first assigned the text Calculating..., then the asynchronous DoTheUltraHardStuff method is scheduled, and then, the method returns. Immediately. This allows the GUI thread to do whatever it needs to do. However - as soon as the asynchronous task is complete and the GUI is free to handle the callback, the execution of btnDoStuff_Click will continue with the result already given (or an exception thrown, of course), back on the GUI thread, allowing you to set the label to the new text including the result of the asynchronous operation.
Asynchronicity is not an absolute property - stuff is asynchronous to some other stuff, and synchronous to some other stuff. It only makes sense with respect to some other stuff.
Hopefully, now you can go back to your original code and understand the part you've misunderstood before. The solutions are multiple, of course, but they depend a lot on how and why you're trying to do what you're trying to do. I suspect you don't actually need to use Task.Run or await at all - the Parallel.ForEach already tries to distribute the CPU work over multiple CPU cores, and the only thing you could do is to make sure other code doesn't have to wait for that work to finish - which would make a lot of sense in a GUI application, but I don't see how it would be useful in a console application with the singular purpose of calculating that single thing.
So yes, you can actually use await for fire-and-forget code - but only as part of code that doesn't prevent the code you want to continue from executing. For example, you could have code like this:
Task<string> result = SomeHardWorkAsync();
Debug.WriteLine("After calling SomeHardWorkAsync");
DoSomeOtherWorkInTheMeantime();
Debug.WriteLine("Done other work.");
Debug.WriteLine("Got result: " + (await result));
This allows SomeHardWorkAsync to execute asynchronously with respect to DoSomeOtherWorkInTheMeantime but not with respect to await result. And of course, you can use awaits in SomeHardWorkAsync without trashing the asynchronicity between SomeHardWorkAsync and DoSomeOtherWorkInTheMeantime.
The GUI example I've shown way above just takes advantage of handling the continuation as something that happens after the task completes, while ignoring the Task created in the async method (there really isn't much of a difference between using async void and async Task when you ignore the result). So for example, to fire-and-forget your method, you could use code like this:
async void Fire(string filename)
{
var result = await ProcessFileAsync(filename);
DoStuffWithResult(result);
}
Fire("MyFile");
This will cause DoStuffWithResult to execute as soon as result is ready, while the method Fire itself will return immediately after executing ProcessFileAsync (up to the first await or any explicit return someTask).
This pattern is usually frowned upon - there really isn't any reason to return void out of an async method (apart from event handlers); you could just as easily return Task (or even Task<T> depending on the scenario), and let the caller decide whether he wants his code to execute synchronously in respect to yours or not.
Again,
async Task FireAsync(string filename)
{
var result = await ProcessFileAsync(filename);
DoStuffWithResult(result);
}
Fire("MyFile");
does the same thing as using async void, except that the caller can decide what to do with the asynchronous task. Perhaps he wants to launch two of those in parallel and continue after all are done? He can just await Task.WhenAll(Fire("1"), Fire("2")). Or he just wants that stuff to happen completely asynchronously with respect to his code, so he'll just call Fire("1") and ignore the resulting Task (of course, ideally, you at the very least want to handle possible exceptions).

async await blocking ui wp8

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.

Categories