I have an async method that get data from a database:
private async Task getDataAsync()
{
await getDataFromDatabaseAsync();
}
I have a contructor that uses this method, in this way:
public MyViewModel()
{
Task.WhenAll(getDataAsync());
//getDataAsync().ConfigureAwait(false);
//next line of code
}
The only way that I get to avoid the applications isn't blocked is using one the two options, both seems to work fine. I can use WhenAll or I can use ConfigureAwait(false).
Another options it is calling the method getDataASync() inside a task, but I guess it is a worse option becase it takes more resources.
So I would like to know which is the differences between WhenAll and ConfigureAwait.
When I use WhenAll in this way, the line of code "next line of code" is run after the async method is finisihed or it will run before finish?
Thanks.
There is a common misconception that when you make a method async, it will be actually executed asynchronously (i.e. on a separate thread). That is not the case: async and await are a means to synchronize already asnychronous code. If you have nothing that is executed on a separate thread, your async code will run fully synchronously to the end.
Since getDataAsync is executed on the same thread as the MyViewModel constructor, you can run into a deadlock, since the thread waits for itself. When you use ConfigureAwait, you can avoid this situation.
Whether you actually should do that is a different question. What you are actually doing with ConfigureAwait is to start the task and to allow the await to continue on a separate context (which can be on a separate thread). Apart from the fact that you are not even using await here, continuation in a different context can become a problem when you want to execute UI operations after the await.
If you want to be sure that you can wait for getDataAsync in your constructor, you can use Task.Run to force execution in the thread pool:
var getDataTask = Task.Run((Func<Task>)getDataAsync);
//Do something else
getDataTask.Wait();
Everything you execute between Task.Run and the Wait() can run during the execution of getDataAsync. Whether parallelism is actually worth it here depends on what else you do until the Wait().
What you are doing in the MyViewModel constructor is to finally synchronize all asynchronous operations and make the execution of the constructor synchronous. If you want to run that operation asynchronously, you would need to start another task to do it. So you should be really sure that beyond that point async is not required anymore. If it is, run the initialization on another async method, await getDataAsync() there and synchronize somewhere up the call chain.
Related
I've been trying to figure out why the UI was blocking from a ViewModel method, and realized that this part of the code:
await Task.WhenAll(getOutput1(), getOutput2());
was the problem. I managed to unblock the UI by using:
await Task.WhenAll(Task.Run(() => getOutput1()), Task.Run(() => getOutput2()));
getOutput1() and getOutput2() are both async with Task return types in the ViewModel, and the code is called from the View.
What's the difference with calling Task.WhenAll when I call Task.Run() and just directly supplying the task?
What's the difference with calling Task.WhenAll when I call Task.Run() and just directly supplying the task?
Calling the methods directly will invoke them on the UI thread. Calling them from within Task.Run will invoke them on a thread pool thread.
Conclusion: getOutput1 and/or getOutput2 are not actually asynchronous. (It is entirely possible for a method to return Task - and thus appear asynchronous - but in reality just block synchronously).
If the methods are pure async operations then you should not use Task.Run while calling them from the UI thread and it will work properly.
However if the methods are also involved in a long running CPU bound work, the UI thread won't be blocked while the async I/O operation is executing but will be while the CPU bound work is.
In this scenario you need the use Task.Run while you are calling the methods even though the methods already look like a async ones, because the methods are actually a combination of synchronous and asynchronous operations and you don't want to block the UI while the synchronous work is done.
Another option instead of using Task.Run from the ViewModel is to use ConfigureAwait(false) while awaiting the I/O async operations in your methods, doing that will inform to the rest of the method after the await part that it does not need the original context it had (which is probably the UI one) and that the rest of the method can also be executed in another ThreadPool thread instead.
Please refer this question for more info about async and await methods that combine I/O and CPU bound works.
When we use await in the code, generally the awaiters capture the context and use that as callback when the awaited task completed successfully. But, since await is generally a No-Op (No Operation), does it make the underlying thread not being reusable until execution of the awaited task completes?
For Example:
public async Task MethodAAsync()
{
// Execute some logic
var test = await MethodB();
// Execute remaining logic
}
Here, since I need the result back to proceed further, I need to await on that. But, since we are awaiting, does it block the underlying thread resulting thread not being used to execute any tasks?
But, since await is generally a No.Op(No Operation), does it make the
underlying thread not being reusable until execution of awaited task
completes?
I'm not sure where you got this information from, but await is certainly not a No-Op. Calling await on a Task, for example, will invoke a logical call to Task.GetAwaiter, where the TaskAwaiter has to implement INotifyCompletion or ICriticalNotifyCompletion interface, which tells the compiler how to invoke the continuation (everything after the first await).
The complete structure of async-await transforms your call to a state-machine such that when the state-machine hits the first await, it will first check to see if the called method completed, and if not will register the continuation and return from that method call. Later, once that method completes, it will re-enter the state-machine in order to complete the method. And that is logically how you see the line after await being hit.
But, since we are awaiting, does it block the underlying thread
resulting thread not being used to execute any tasks?
No, creating an entire mechanism only to block the calling thread would be useless. async-await allow you to actually yield the calling thread back to the caller which allows him to continue execution on that same thread, while the runtime takes care of queuing and invoking the completion.
In short, no, it doesn't block your thread.
More info: http://blog.stephencleary.com/2013/11/there-is-no-thread.html
The thread has a local queue of Tasks. Once it hits an await it will pick up another Task from it's queue (assuming all methods up it's stack are awaited). If the queue is empty, it will try to get a Task from the global queue, and if it's empty too - the thread will try to get a Task from another thread's own local queue. In a simple program, where all threads might get "out of Tasks" - the thread will remain idle until one of the Tasks returns.
In the following code, in the B method, the code Trace.TraceInformation("B - Started"); never gets called.
Should the method be running in parallel?
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
private static async Task A()
{
for (;;)
{
}
}
private static async Task B()
{
Trace.TraceInformation("B - Started");
}
static void Main(string[] args)
{
var tasks = new List<Task> { A(), B() };
Task.WaitAll(tasks.ToArray());
}
}
}
Short answer
No, as you wrote your two async methods, they are indeed not running in parallel. Adding await Task.Yield(); to your first method (e.g. inside the loop) would allow them to do so, but there are more reasonable and straightforward methods, highly depending on what you actually need (interleaved execution on a single thread? Actual parallel execution on multiple threads?).
Long answer
First of all, declaring functions as async does not inherently make them run asynchronously or something. It rather simplifies the syntax to do so - read more about the concepts here: Asynchronous Programming with Async and Await
Effectively A is not asynchronous at all, as there is not a single await inside its method body. Instructions up to the first use of await run synchronously like a regular method would.
From then on, the object that you await determines what happens next, i.e. the context that the remaining method runs in.
To force execution of a task to happen on another thread, use Task.Run or similar.
In this scenario, adding await Task.Yield() does the trick since the current synchronization context is null and this happens to indeed cause the task scheduler (should be ThreadPoolTaskScheduler) to execute the remaining instuctions on a thread-pool thread - some environment or configuration might cause you to only have one of them, so things would still not run in parallel.
Summary
The moral of the story is: Be aware of the differences between two concepts:
concurrency (which is enabled by using async/await reasonably) and
parallelism (which only happens when concurrent tasks get scheduled the right way or if you enforce it using Task.Run, Thread, etc. in which case the use of async is completely irrelevant anyway)
The async modifier is not a magic spawn-a-thread-here marker. It's sole purpose is to let the compiler know a method might depend on some asynchronous operation (A complex data-processing thread, I/O...) so it has to setup a state machine to coordinate the callbacks resulting from those asynchronous operations.
To make A run on another thread you would invoke it using Task.Run which wraps the invocation on a new thread with a Task object, which you can await. Be aware that await-ing a method does not mean your code runs in parallel to A's execution all by itself: It will until the very line you await the Task object, telling the compiler you need the value that the Task object returns. In this case await-ing Task.Run(A) will effectively make your program run forever, waiting for A to return, something that will never happen (barring computer malfunction).
Do have in mind that marking a method as async but not actually awaiting anything will only have the effect of a compiler warning. If you await something that is not truly async (It returns immediately on the calling thread with something like Task.FromResult) it will mean your program takes a runtime speed penalty. It is very slight, however.
No, the methods shown are not expected to "run in parallel".
Why B is never called - you have list of tasks tasks constructed via essentially series of .Add calls - and first is result of A() is added. Since the A method does not have any await it will run to the completion synchronously on the same thread. And after that B() would be called.
Now A will never complete (it is sitting in infinite loop) so really code will not even reach call to B.
Note that even if creation would succeed code never finish WaitAll as A still sits in infinite loop.
If you want methods to "run in parallel" you need to either run them implicitly/explicitly on new threads (i.e. with Task.Run or Thread.Start) or for I/O bound calls let method to release thread with await.
What would be an appropriate way to re-write my SlowMethodAsync async method, which executes a long running task, that can be awaited, but without using Task.Run?
I can do it with Task.Run as following:
public async Task SlowMethodAsync()
{
await Task.Run(() => SlowMethod());
}
public void SlowMethod()
{
//heavy math calculation process takes place here
}
The code, as it shown above, will spawn a new thread from a thread-pool. If it can be done differently, will it run on the invocation thread, and block it any way, as the SlowMethod content is a solid chunk of math processing without any sort of yielding and time-slice surrendering.
Just to clarify that I need my method to stay asynchronous, as it unblocks my UI thread. Just looking for another possible way to do that in a different way to how it's currently done, while keeping async method signature.
async methods are meant for asynchronous operations. They enable not blocking threads for non-CPU-bound work. If your SlowMethod has any IO-bound operations which are currently executed synchronously (e.g. Stream.Read or Socket.Send) you can exchange these for async ones and await them in your async method.
In your case (math processing) the code's probably mostly CPU-bound, so other than offloading the work to a ThreadPool thread (using Task.Run) there's no reason to use async as all. Keep SlowMethod as it is and it will run on the calling thread.
Regarding your update: You definitely want to use Task.Run (or one of the Task.Factory.StartNew overloads) to offload your work to a different thread.
Actually, for your specific case, you should use
await Task.Factory.StartNew(() => SlowMethod(), TaskCreationOptions.LongRunning)
which will allow the scheduler to run your synchronous task in the appropriate place (probably in a new thread) so it doesn't gum up the ThreadPool (which isn't really designed for CPU heavy workloads).
Wouldn't it be better just to call SlowMethod synchronously? What are you gaining by awaiting it?
Consider an asynchronous (*Async / async) function that is called twice, one time with await and other without it.
If I use await, will it wait until the asynchronous function is executed and then execute the next line?
await db.SaveChangesAsync();
//Some code here
And, if I don't use await, will it continue with executing the code below it without waiting for the asynchronous function to complete?
db.SaveChangesAsync();
//Some code here
Am, I right over here or await is mandatory when it comes to async functions?
If I use await, will it wait till the async function is executed and then execute the next line.
That depends on the method returns. It returns a Task[<T>], which represents a future value. If the Task is already completed, it keeps running synchronously. Otherwise, the remaining portion of the current method is added as a continuation - a delegate callback that is invoked when the asynchronous portion reports completion.
What it does not do, in either case, is block the calling thread while the asynchronous part continues.
And, if I don't use await, will it continue with executing the code below it without waiting for the async function to complete.
Yes
...or await is mandatory when it comes to async functions?
When invoking them? Not mandatory, but it does make things convenient. Usually, such functions return a Task[<T>], which can also be consumed via different code. You could use .ContinueWith(...), .Wait, .Result, etc. Or you could just ignore the Task completely. The last is a bad idea, because exceptions on asynchronous functions need to go somewhere: very bad things happen if exceptions are not observed.
When writing them, however: if you write an async method and don't have an await keyword in there, the compiler will present a warning indicating that you're probably doing something wrong. Again, not strictly mandatory, but highly recommended.