Having read a /lot/ of documentation on the async await pattern I thought I had a pretty good handle on the pattern. I read all about async all the way then read another article that mentions 'if it runs in under 50 milliseconds don't async it'. It seems there is conflicting information and/or opinions and I have managed to just confuse myself. I have also read that Task.Yield() will force an async decorated method to run asynchronously.
Given the following code:
static async Task MethodA() {
await MethodB().ConfigureAwait(false);
}
static async Task MethodB() {
await Task.Yield();
MethodC();
}
static void MethodC() {
// do some synchronous stuff
}
static async Task Main(string[] args) {
var task1 = Task.Run(() => MethodA().ConfigureAwait(false));
var task2 = Task.Run(() => MethodB().ConfigureAwait(false));
await Task.WhenAll(new List<Task>() { task1, task2 });
}
Will MethodC run synchronously or asynchronously, I assumed asynchronously as it was called from an asynchronous method. Also, is Task.Yield necessary at all?
To be honest this is doing my head in, every article I have read delves deeper and deeper into the async await pattern with the whys and wherefores and is just adding more complexity to the question. Just looking for a simple answer.
Will MethodC run synchronously or asynchronously
Synchronously. It has a synchronous signature, so it will always run synchronously.
I assumed asynchronously as it was called from an asynchronous method
The context from which it is called is irrelevant to how MethodC will run.
is Task.Yield necessary at all
Well it will force MethodB to yield a Task before MethodC runs, but this will be incomplete until MethodC finishes, and because MethodC is synchronous (does not release the thread) it achieves nothing useful.
Just looking for a simple answer
async bubbles up the call stack, and because you are not consuming an async method here (MethodC is synchronous) you should not be using async at all.
This answer contains general info and advices, and it's not focused on the code that you posted.
Being confused while learning async-await is OK. Getting a perfect understanding of async-await without going through a confusion phase is practically almost impossible IMHO.
The await Task.Yield(), await Task.Delay(1), await Task.Run(() => { }), and .ConfigureAwait(false) are dirty hacks that people sometimes use out of frustration that an explicit way to switch imperatively to the ThreadPool context does not exist (in the standard libraries). A SwitchTo method existed in some pre-prelease .NET version, then it was removed for technical reasons, then the technical reasons were eliminated, reintroducing the method never became a high enough priority, and so it didn't happen. It may happen in the future, but don't hold your breath. It is currently available in the Microsoft.VisualStudio.Threading package, if you want it.
You don't need any of these hacks to write async-await code successfully. If you want to offload work to the ThreadPool, there is the Task.Run method that does the job perfectly.
Offloading work to the ThreadPool should be done at the "application code" level, not at the "library code" level. You can read this article to understand why exposing asynchronous wrappers for synchronous methods is not a good idea.
Related
The task API feels sort of like a pit of failure, given how every possible thing I could do with it comes with more DON'T than DO. But I'm trying to use it more, and I'm confused about the entire issue of async void.
My problem happens in a place where my application's used a local data file forever, and because it was fast synchronous calls were used. Now some remote sources are an option, and they have enough latency I'm switching it all to be asynchronous.
So I've got a method that maybe looks like this:
void InitializeData() {
SomeProperty = _dataSource.Load(...);
}
The naive thing I want to do for low-friction is:
Task InitializeDataAsync() {
return Task.Run(() => {
SomeProperty = _dataSource.Load(...);
});
}
But there are SO many articles about how terrible it is to use async void, and they seem to blur with discussion of returning a Task. So is my best option really to write it like:
Task<DataType> FetchDataAsync() {
return _dataSource.LoadAsync(...);
}
...then hunt down all the callers and make them comply?
I feel like the argument people make is that async void is bad because of the different behavior of async Task and the dreaded UnobservedTaskException when you use await. In this situation, I'm very unlikely to ever be using await. Or if I do use await, it's always going to have a try/catch around it because we're already paranoid about UnobservedTaskException.
So:
Is "Don't use async void" the same thing as "Don't use Task?
If you don't use await, does it mitigate that?
If you do use await, does always wrapping it with a try/catch mitigate the issue?
async void is not the same as returning a Task. The problem with async void is there is no way to observe task exceptions (other then the global exception handler), and no way to wait for the task to complete (you actually can't await an async void method because there is nothing to await), this is why it should be avoided.
Returning Task does not have these problems, if you await it you know when it completes and you will get exceptions where you await so returning a Task is perfectly acceptable.
It looks like you're just confused. The await/async API is incredibly simple. The only confusing part is understanding the difference between await/async API and the Task API. I won't go into great detail about this as the Stephen Cleary's blog clearly covers this, but here is the important excerpt:
To reiterate a sentence from my last post, use Task.Run to call CPU-bound methods (from GUI threads). Do not use it just to “provide something awaitable for my async method to use”.
next...
The naive thing I want to do for low-friction is:
Task InitializeDataAsync() {
return Task.Run(() => {
SomeProperty = _dataSource.Load(...);
});
}
This is a clear case of offloading Sync code into a Async wrapper which doesn't really do any good.
But there are SO many articles about how terrible it is to use async void,
This is clearly not a async void method. This is a non-async Task returning method. Here is an async void method:
async void InitializeDataAsync() {
await Task.Run(() => {
SomeProperty = _dataSource.Load(...);
});
}
they seem to blur with discussion of returning a Task.
I've not read anything that blurs this information. It's pretty simple; if you have an async method, always return Task or Task<T> (except as stated below). The difference between using these two (Task or Task<T>) is purely design/architecture.
So is my best option really to write it like:
Best is really an opinion here. Both of these work and don't forget async/wait
async Task<DataType> FetchDataAsync() {
return await _dataSource.LoadAsync(...);
}
async Task FetchDataAsync() {
_data = await _dataSource.LoadAsync(...);
}
I feel like the argument people make is that async void is bad because of the different behavior of async Task and the dreaded UnobservedTaskException when you use await.
The most important difference is how exceptions are handled:
Excerpt:
Async void methods have different error-handling semantics. When an exception is thrown out of an async Task or async Task method, that exception is captured and placed on the Task object. With async void methods, there is no Task object, so any exceptions thrown out of an async void method will be raised directly on the SynchronizationContext that was active when the async void method started.
So
Or if I do use await, it's always going to have a try/catch around it because we're already paranoid about UnobservedTaskException.
This means that you can't catch an exception by try/catch around async void. That is a huge problem!
Is "Don't use async void" the same thing as "Don't use Task?"
Well this is apples and oranges. Yes: don't use async void unless you're using them for async event handlers.
Don't use Task's unless they are CPU bound or you're using a Framework call (or you've correctly wrapped your own method which uses IO Completion Ports).
If you don't use await, does it mitigate that?
Hopefully by now you understand that await/async is different from a Task, and what you're trying to do is write all await/async code.
If you do use await, does always wrapping it with a try/catch mitigate the issue?
Depends, as stated above.
I am pretty sure, this was answered already and I read many related stuff but somehow I am not getting it to work in my code. Here is the exact code base.
I have this async method in my library, that returns a string upon doing some DB entries:
public class MyLibrary
{
public async Task<string> DoSomethingAsync()
{
return await DoAsync();
}
// some private method, with multiple parameters
private Task<string> DoAsync()
{
return Task.Run(() => Do());
}
}
Now on UI, below resulted a frozen state or deadlock:
var myTask = MyLibraryobject.DoSomethingAsync();
console.Write(myTask.Result);
Since my call is awaitable, I think, UI thread waits for my call to finish its business and populate the result, doesn't it? Or since the call is running on another thread, the task might not yet completed when my cursor hits the line 2. So what now? the cursor will wait till the task gets completed or the line 2 gets executed whenever the task gets completed? sounds synchronous to me..
Also if at all, I want to 'exlicitly' wait till the task gets finished, how do i enforce that? some posts, suggested in doing like below, which gave me the result, but created some more confusion:
var myTask = Task.Run(async () => await MyLibraryobject.DoSomethingAsync());
myTask.Wait();
console.Write(myTask.Result);
What is happening above? why should i create another task and set it to wait? can't I wait for the thread, used by the async method? Again, i am clearly missing some basic stuff here.
Lastly, this is an async call, but the UI thread is waiting for it to be completed thus gives me an impression that it's synchronous. Am I thinking it right? Then what is the main purpose of async methods, which return something, and UI waits for it to complete?
Also what's the difference between a fire-and-forget call being non-async and async? is there any benefit of returning Task, instead of void, for such calls?
I am pretty sure, some broken link that connects all these pieces together in my brain. Can someone explain that to me, please??
You should probably start with my async intro and follow up with my article on async best practices. They answer almost all your questions.
For the details...
how and when to fetch return from awaitable(async) method
You should use await to get the result from an async task.
I have this async method in my library, that returns a string upon doing some DB entries
Then it should not be using Task.Run. It should be using naturally-asynchronous APIs, e.g., Entity Framework's FirstAsync.
Since my call is awaitable, I think, UI thread waits for my call to finish its business and populate the result, doesn't it?
No. The UI is blocking because your code is calling Result. Result is a blocking call.
sounds synchronous to me..
That's because you're making it synchronous by using Result. If you use await, the code will execute serially, but asynchronously.
Also if at all, I want to 'exlicitly' wait till the task gets finished, how do i enforce that?
Your code is already doing that. It's explicitly blocking until the task is complete. If you change it to properly use await, it will be explicitly waiting (but not blocking) until the task is complete.
some posts, suggested in doing like below
No. Don't use Task.Run unnecessarily.
can't I wait for the thread, used by the async method?
Pure async methods don't have threads that they use.
Then what is the main purpose of async methods, which return something, and UI waits for it to complete?
Async makes sense when it's consumed with await.
Now on UI, below resulted a frozen state or deadlock:
var myTask = MyLibraryobject.DoSomethingAsync();
This is blocking the UI because it is not awaited. You simply need to await an async method
string res = await MyLibraryobject.DoSomethingAsync();
and the above should be placed in the UI inside an async context too.
Edit - reply to comment do "you mean another wrapper async method, which returns Task<string>..."? No,I don't. When I wrote "inside an async context" I meant to add the async keyword to a subscribed event, like a button click, if you are in the code behind or to your delegate command implementation, if you are in a more advanced MVVM implementation of the GUI.
Furthermore, your class library is supposed to do something truly asynchronous, not just starting a task and wrapping it inside a formally async method, like it is your DoAsync.
Edit - in reply to comment "how should avoid" it? If you can't do async all the way, just keep the library and the API sync and unblock the UI by starting a separate thread to call the sync api.
I just came across some code like:
var task = Task.Run(async () => { await Foo.StartAsync(); });
task.Wait();
(No, I don't know the inner-workings of Foo.StartAsync()). My initial reaction would be get rid of async/await and rewrite as:
var task = Foo.StartAsync();
task.Wait();
Would that be correct, or not (again, knowing nothing at all about Foo.StartAsync()). This answer to What difference does it make - running an 'async' action delegate with a Task.Run ... seems to indicate there may be cases when it might make sense, but it also says "To tell the truth, I haven't seen that many scenarios ..."
Normally, the intended usage for Task.Run is to execute CPU-bound code on a non-UI thread. As such, it would be quite rare for it to be used with an async delegate, but it is possible (e.g., for code that has both asynchronous and CPU-bound portions).
However, that's the intended usage. I think in your example:
var task = Task.Run(async () => { await Foo.StartAsync(); });
task.Wait();
It's far more likely that the original author is attempting to synchronously block on asynchronous code, and is (ab)using Task.Run to avoid deadlocks common in that situation (as I describe on my blog).
In essence, it looks like the "thread pool hack" that I describe in my article on brownfield asynchronous code.
The best solution is to not use Task.Run or Wait:
await Foo.StartAsync();
This will cause async to grow through your code base, which is the best approach, but may cause an unacceptable amount of work for your developers right now. This is presumably why your predecessor used Task.Run(..).Wait().
Mostly yes.
Using Task.Run like this is mostly used by people who don't understand how to execute an async method.
However, there is a difference. Using Task.Run means starting the async method on a ThreadPool thread.
This can be useful when the async method's synchronous part (the part before the first await) is substantial and the caller wants to make sure that method isn't blocking.
This can also be used to "get out of" the current context, for example where there isn't a SynchronizationContext.
It's worth noting that your method has to be marked async to be able to use the await keyword.
The code as written seems to be a workaround for running asynchronous code in a synchronous context. While I wouldn't say you should never ever do this, using async methods is preferable in almost every scenario.
// use this only when running Tasks in a synchronous method
// use async instead whenever possible
var task = Task.Run(async () => await Foo.StartAsync());
task.Wait();
Async methods, like your example of Foo.StartAsync(), should always return a Task object. This means that using Task.Run() to create another task is usually redundant in an async method. The task returned by the async method can simply be awaited by using the await keyword. The only reason you should use Task.Run() is when you are performing CPU-bound work that needs to be performed on a separate thread. The task returned by the async method can simply be awaited by using the await keyword. You can read more in depth details in Microsoft's guide to async programming.
In an async method, your code can be as simple as:
await Foo.StartAsync();
If you want to perform some other work while the task is running, you can assign the function to a variable and await the result (task completion) later.
For example:
var task = Foo.StartAsync();
// do some other work before waiting for task to finish
Bar();
Baz();
// now wait for the task to finish executing
await task;
With CPU-bound work that needs to be run on a separate thread, you can use Task.Run(), but you await the result instead of using the thread blocking Task.Wait():
var task = Task.Run(async () => await Foo.StartAsync());
// do some other work before waiting for task to finish
Bar();
Baz();
// now wait for the task to finish executing
await task;
I'm using async/await and Task a lot but have never been using Task.Yield() and to be honest even with all the explanations I do not understand why I would need this method.
Can somebody give a good example where Yield() is required?
When you use async/await, there is no guarantee that the method you call when you do await FooAsync() will actually run asynchronously. The internal implementation is free to return using a completely synchronous path.
If you're making an API where it's critical that you don't block and you run some code asynchronously, and there's a chance that the called method will run synchronously (effectively blocking), using await Task.Yield() will force your method to be asynchronous, and return control at that point. The rest of the code will execute at a later time (at which point, it still may run synchronously) on the current context.
This can also be useful if you make an asynchronous method that requires some "long running" initialization, ie:
private async void button_Click(object sender, EventArgs e)
{
await Task.Yield(); // Make us async right away
var data = ExecuteFooOnUIThread(); // This will run on the UI thread at some point later
await UseDataAsync(data);
}
Without the Task.Yield() call, the method will execute synchronously all the way up to the first call to await.
Internally, await Task.Yield() simply queues the continuation on either the current synchronization context or on a random pool thread, if SynchronizationContext.Current is null.
It is efficiently implemented as custom awaiter. A less efficient code producing the identical effect might be as simple as this:
var tcs = new TaskCompletionSource<bool>();
var sc = SynchronizationContext.Current;
if (sc != null)
sc.Post(_ => tcs.SetResult(true), null);
else
ThreadPool.QueueUserWorkItem(_ => tcs.SetResult(true));
await tcs.Task;
Task.Yield() can be used as a short-cut for some weird execution flow alterations. For example:
async Task DoDialogAsync()
{
var dialog = new Form();
Func<Task> showAsync = async () =>
{
await Task.Yield();
dialog.ShowDialog();
}
var dialogTask = showAsync();
await Task.Yield();
// now we're on the dialog's nested message loop started by dialog.ShowDialog
MessageBox.Show("The dialog is visible, click OK to close");
dialog.Close();
await dialogTask;
// we're back to the main message loop
}
That said, I can't think of any case where Task.Yield() cannot be replaced with Task.Factory.StartNew w/ proper task scheduler.
See also:
"await Task.Yield()" and its alternatives
Task.Yield - real usages?
One use of Task.Yield() is to prevent a stack overflow when doing async recursion. Task.Yield() prevents syncronous continuation. Note, however, that this can cause an OutOfMemory exception (as noted by Triynko). Endless recursion is still not safe and you're probably better off rewriting the recursion as a loop.
private static void Main()
{
RecursiveMethod().Wait();
}
private static async Task RecursiveMethod()
{
await Task.Delay(1);
//await Task.Yield(); // Uncomment this line to prevent stackoverlfow.
await RecursiveMethod();
}
Task.Yield() is like a counterpart of Thread.Yield() in async-await but with much more specific conditions. How many times do you even need Thread.Yield()? I will answer the title "when would you use Task.Yield()" broadly first. You would when the following conditions are fulfilled:
want to return the control to the async context (suggesting the task scheduler to execute other tasks in the queue first)
need to continue in the async context
prefer to continue immediately when the task scheduler is free
do not want to be cancelled
prefer shorter code
The term "async context" here means "SynchronizationContext first then TaskScheduler". It was used by Stephen Cleary.
Task.Yield() is approximately doing this (many posts get it slightly wrong here and there):
await Task.Factory.StartNew(
() => {},
CancellationToken.None,
TaskCreationOptions.PreferFairness,
SynchronizationContext.Current != null?
TaskScheduler.FromCurrentSynchronizationContext():
TaskScheduler.Current);
If any one of the conditions is broken, you need to use other alternatives instead.
If the continuation of a task should be in Task.DefaultScheduler, you normally use ConfigureAwait(false). On the contrary, Task.Yield() gives you an awaitable not having ConfigureAwait(bool). You need to use the approximated code with TaskScheduler.Default.
If Task.Yield() obstructs the queue, you need to restructure your code instead as explained by noseratio.
If you need the continuation to happen much later, say, in the order of millisecond, you would use Task.Delay.
If you want the task to be cancellable in the queue but do not want to check the cancellation token nor throw an exception yourself, you need to use the approximated code with a cancellation token.
Task.Yield() is so niche and easily dodged. I only have one imaginary example by mixing my experience. It is to solve an async dining philosopher problem constrained by a custom scheduler. In my multi-thread helper library InSync, it supports unordered acquisitions of async locks. It enqueues an async acquisition if the current one failed. The code is here. It needs ConfigureAwait(false) as a general purpose library so I need to use Task.Factory.StartNew. In a closed source project, my program needs to execute significant synchronous code mixed with async code with
a high thread priority for semi-realtime work
a low thread priority for some background work
a normal thread priority for UI
Thus, I need a custom scheduler. I could easily imagine some poor developers somehow need to mix sync and async code together with some special schedulers in a parallel universe (one universe probably does not contain such developers); but why wouldn't they just use the more robust approximated code so they do not need to write a lengthy comment to explain why and what it does?
Task.Yield() may be used in mock implementations of async methods.
I ran into this peculiar case with tasks and Task.Factory. So here's my piece of code.
public Task CreateAndStartSyncTask()
{
return Task.Factory.StartNew(async () =>
{
... do stuff ...
await Task.Delay(500);
... do more stuff ...
}
}
public void Synchronize()
{
var syncTask = CreateAndStartSyncTask();
syncTask.Wait(mTimeout);
switch(syncTask.Status) {
case TaskStatus.RanToCompletion:
// VICTORY!
break;
default:
throw syncTask.Exception;
}
}
So here my problem is that when I run this glorious piece of code, I get to the switch case BEFORE "... do more stuff ...". The task then continues running until completion. This is not desired functionality as I would really prefer for the task to complete.
That being said, having it in it's own task here is slightly redundant in this specific context given the fact that it is treated in a synchronous manner but I can't fully disclose the code and I really need to understand the whole task completion mentality.
What's up and how can I actually check whether a task is REALLY concluded?
Don't use Task.Factory.StartNew. Use Task.Run instead. Both Stephen Toub and I have blog posts that describe this in detail.
In summary, StartNew doesn't understand async methods. The Task it returns only represents the first synchronous portion of the method. To use StartNew, you either have to call Unwrap or do a double await. It's far better to use Task.Run, which does understand async methods.
Also, you don't want to block on async tasks (i.e., the Wait in Synchronize). Instead, you should await them. If you block on them, you can easily encounter a deadlock situation that I describe on my blog.