When should you use Task.Run() rather than await? - c#

I am storing the state of my data model. I clone the data model and then want to have it written to "disk" asynchronously.
Should I be using Task.Run() which runs it on a background thread?
Or should I just make it an async function and not await on it? (this will make it run on the UI thread)
Similar stuff to this, but my question is a bit different:
async Task.Run with MVVM
And what is the criteria to decide which to choose?
Thanks!

You should use Task.Run for CPU-based work that you want to run on a thread pool thread.
In your situation, you want to do I/O based work without blocking the UI, so Task.Run won't get you anything (unless you don't have asynchronous I/O APIs available).
As a side note, you definitely do want to await this work. This makes error handling much cleaner.
So, something like this should suffice:
async void buttonSaveClick(..)
{
buttonSave.Enabled = false;
try
{
await myModel.Clone().SaveAsync();
}
catch (Exception ex)
{
// Display error.
}
buttonSave.Enabled = true;
}

I don't think it matters. As far as I know, both methods get dispatched to a thread in the thread pool.
Using async will make the async method run on a background thread and continue on the thread that started it when the async method is finished. You can imagine the compiler seeing the await keyword, put the awaited method in a background thread and wiring up events to notice when the asynch method is finished. Therefore this might be the better choice if you want to show a UI change because of the successful save, and because this is lesser code of course.
Task.Run() would be nicer when you for any reason don't want to put the code in an async method, for example because you want the calling method itself not be async. Also, there's lesser event marshaling involved, but I heavily doubt that there's any performance difference at all.

Related

Should I use Task.Run to wait tasks in a synchronous context?

I have an ASPX page which I cannot convert to async but which uses some async methods in a synchronous context. The way it invokes them is like so:
public void MySyncMethod()
{
var myTask = Task.Run(() => _myField.DoSomethingAsync());
myTask.Wait();
//use myTask.Result
}
Is there any difference between doing that and the following as far as async/await and/or blocking goes?
public void MySyncMethod()
{
var myTask = _myField.DoSomethingAsync(); //just get the Task direct, no Task.Run
myTask.Wait();
//use myTask.Result
}
I assume a previous developer added the Task.Run for a reason. But I am having issues which accessing things in HttpContext as the work is being run on a different thread.
Is there a reason to use Task.Run here?
Is there any difference between doing that and the following as far as
async/await and/or blocking goes?
Yes the first block of code uses a thread pool thread then waits for this to return, so your using two threads not one. They both block.
I assume a previous developer added the Task.Run for a reason.
Yes, blocking (directly) on async code from an ASP.Net context is a bad idea and can cause deadlocks. So you second block of code is more efficent (in thread usage) but suffers from serious deadlock issues.
The correct solution here is to make public void MySyncMethod() async itself (public async Task MySyncMethod()). Both these solutions have drawbacks and the only real way out is to make the whole call stack async. If you can do this, do it.
If you can't call an async method from another async method then Task.Run is the way to go. See How to call asynchronous method from synchronous method in C#? for more details.
If you want HttpContext inside your thread have a read though Using HttpContext in Async Task I would definitely favour:
Make every thing async
Or the Read the values from the context then pass them
Options of those answers and keep in mind
First off, you're not creating a copy of the object, you're just
copying the reference to the object.HttpContext isn't a
struct.....etc
The internal workings of asynchronous code based on async/await is fundamentally different than tasks started by Task.Run. async/await tasks are promise based and depend on the caller cooperating with returning the execution back to the asynchronous method when appropriate. Tasks started by Task.Run however are usually started on a parallel thread taken from the thread pool and do not depend on the caller's cooperation to continue execution when appropriate.
This constellation leads to the problem that you can not treat a promise based task the same as the other tasks, since the promise based task might wait for the callers cooperation to return the execution, which might never occur since the other task is executed independently and might wait for the caller. The result is a deadlock.
The solution is a specific Task.Run overload that will create a proxy for an existing task-based method that allows proper execution of a promise based task. It is safe to call Wait on this proxy. That's why the other developer used this construct. He could have also simplified the call and avoided an anonymous method like this:
var myTask = Task.Run(_myField.DoSomethingAsync);
Task.Run is used to run code asynchronously.
Be clear that it returns Task and needs to be awaited. Here's an example:
Task myTask = Task.Run(() => DoSomething());
await myTask;

Why use async when I have to use await?

I've been stuck on this question for a while and haven't really found any useful clarification as to why this is.
If I have an async method like:
public async Task<bool> MyMethod()
{
// Some logic
return true;
}
public async void MyMethod2()
{
var status = MyMethod(); // Visual studio green lines this and recommends using await
}
If I use await here, what's the point of the asynchronous method? Doesn't it make the async useless that VS is telling me to call await? Does that not defeat the purpose of offloading a task to a thread without waiting for it to finish?
Does that not defeat the purpose of offloading a task to a thread without waiting for it to finish?
Yes, of course. But that's not the purpose of await/async. The purpose is to allow you to write synchronous code that uses asynchronous operations without wasting threads, or more generally, to give the caller a measure of control over the more or less asynchronous operations.
The basic idea is that as long as you use await and async properly, the whole operation will appear to be synchronous. This is usually a good thing, because most of the things you do are synchronous - say, you don't want to create a user before you request the user name. So you'd do something like this:
var name = await GetNameAsync();
var user = await RemoteService.CreateUserAsync(name);
The two operations are synchronous with respect to each other; the second doesn't (and cannot!) happen before the first. But they aren't (necessarily) synchronous with respect to their caller. A typical example is a Windows Forms application. Imagine you have a button, and the click handler contains the code above - all the code runs on the UI thread, but at the same time, while you're awaiting, the UI thread is free to do other tasks (similar to using Application.DoEvents until the operation completes).
Synchronous code is easier to write and understand, so this allows you to get most of the benefits of asynchronous operations without making your code harder to understand. And you don't lose the ability to do things asynchronously, since Task itself is just a promise, and you don't always have to await it right away. Imagine that GetNameAsync takes a lot of time, but at the same time, you have some CPU work to do before it's done:
var nameTask = GetNameAsync();
for (int i = 0; i < 100; i++) Thread.Sleep(100); // Important busy-work!
var name = await nameTask;
var user = await RemoteService.CreateUserAsync(name);
And now your code is still beautifuly synchronous - await is the synchronization point - while you can do other things in parallel with the asynchronous operations. Another typical example would be firing off multiple asynchronous requests in parallel but keeping the code synchronous with the completion of all of the requests:
var tasks = urls.Select(i => httpClient.GetAsync(i)).ToArray();
await Task.WhenAll(tasks);
The tasks are asynchronous in respect to each other, but not their caller, which is still beautifuly synchronous.
I've made a (incomplete) networking sample that uses await in just this way. The basic idea is that while most of the code is logically synchronous (there's a protocol to be followed - ask for login->verify login->read loop...; you can even see the part where multiple tasks are awaited in parallel), you only use a thread when you actually have CPU work to do. Await makes this almost trivial - doing the same thing with continuations or the old Begin/End async model would be much more painful, especially with respect to error handling. Await makes it look very clean.
If I use await here, what's the point of the asynchronous method?
await does not block thread. MyMethod2 will run synchronously until it reaches await expression. Then MyMethod2 will be suspended until awaited task (MyMethod) is complete. While MyMethod is not completed control will return to caller of MyMethod2. That's the point of await - caller will continue doing it's job.
Doesn't it make the async useless that VS is telling me to call await?
async is just a flag which means 'somewhere in the method you have one or more await'.
Does that not defeat the purpose of offloading a task to a thread
without waiting for it to finish?
As described above, you don't have to wait for task to finish. Nothing is blocked here.
NOTE: To follow framework naming standards I suggest you to add Async suffix to asynchronous method names.
An async method is not automatically executed on a different thread. Actually, the opposite is true: an async method is always executed in the calling thread. async means that this is a method that can yield to an asynchronous operation. That means it can return control to the caller while waiting for the other execution to complete. So asnync methods are a way to wait for other asynchronoous operations.
Since you are doing nothing to wait for in MyMethod2, async makes no sense here, so your compiler warns you.
Interestingly, the team that implemented async methods has acknowledged that marking a method async is not really necessary, since it would be enough to just use await in the method body for the compiler to recognize it as async. The requirement of using the async keyword has been added to avoid breaking changes to existing code that uses await as a variable name.

await Task.Run vs await

I've searched the web and seen a lot of questions regarding Task.Run vs await async, but there is this specific usage scenario where I don't not really understand the difference. Scenario is quite simple i believe.
await Task.Run(() => LongProcess());
vs
await LongProcess());
where LongProcess is a async method with a few asynchronous calls in it like calling db with await ExecuteReaderAsync() for instance.
Question:
Is there any difference between the two in this scenario? Any help or input appreciated, thanks!
Task.Run may post the operation to be processed at a different thread. That's the only difference.
This may be of use - for example, if LongProcess isn't truly asynchronous, it will make the caller return faster. But for a truly asynchronous method, there's no point in using Task.Run, and it may result in unnecessary waste.
Be careful, though, because the behaviour of Task.Run will change based on overload resolution. In your example, the Func<Task> overload will be chosen, which will (correctly) wait for LongProcess to finish. However, if a non-task-returning delegate was used, Task.Run will only wait for execution up to the first await (note that this is how TaskFactory.StartNew will always behave, so don't use that).
Quite often people think that async-await is done by several threads. In fact it is all done by one thread.
See the addition below about this one thread statement
The thing that helped me a lot to understand async-await is this interview with Eric Lippert about async-await. Somewhere in the middle he compares async await with a cook who has to wait for some water to boil. Instead of doing nothing, he looks around to see if there is still something else to do like slicing the onions. If that is finished, and the water still doesn't boil he checks if there is something else to do, and so forth until he has nothing to do but wait. In that case he returns to the first thing he waited for.
If your procedure calls an awaitable function, we are certain that somewhere in this awaitable function there is a call to an awaitable function, otherwise the function wouldn't be awaitable. In fact, your compiler will warn you if you forget to await somewhere in your awaitable function.
If your awaitable function calls the other awaitable function, then the thread enters this other function and starts doing the things in this function and goes deeper into other functions until he meets an await.
Instead of waiting for the results, the thread goes up in his call stack to see if there are other pieces of code he can process until he sees an await. Go up again in the call stack, process until await, etc. Once everyone is awaiting the thread looks for the bottom await and continues once that is finished.
This has the advantage, that if the caller of your awaitable function does not need the result of your function, but can do other things before the result is needed, these other things can be done by the thread instead of waiting inside your function.
A call without waiting immediately for the result would look like this:
private async Task MyFunction()
{
Task<ReturnType>taskA = SomeFunctionAsync(...)
// I don't need the result yet, I can do something else
DoSomethingElse();
// now I need the result of SomeFunctionAsync, await for it:
ReturnType result = await TaskA;
// now you can use object result
}
Note that in this scenario everything is done by one thread. As long as your thread has something to do he will be busy.
Addition. It is not true that only one thread is involved. Any thread who has nothing to do might continue processing your code after an await. If you check the thread id, you can see that this id can be changed after the await. The continuing thread has the same context as the original thread, so you can act as if it was the original thread. No need to check for InvokeRequired, no need to use mutexes or critical sections. For your code this is as if there is one thread involved.
The link to the article in the end of this answer explains a bit more about thread context
You'll see awaitable functions mainly where some other process has to do things, while your thread just has to wait idly until the other thing is finished. Examples are sending data over the internet, saving a file, communicating with a database etc.
However, sometimes some heavy calculations has to be done, and you want your thread to be free to do something else, like respond to user input. In that case you can start an awaitable action as if you called an async function.
Task<ResultType> LetSomeoneDoHeavyCalculations(...)
{
DoSomePreparations()
// start a different thread that does the heavy calculations:
var myTask = Task.Run( () => DoHeavyCalculations(...))
// now you are free to do other things
DoSomethingElse();
// once you need the result of the HeavyCalculations await for it
var myResult = await myTask;
// use myResult
...
}
Now a different thread is doing the heavy calculations while your thread is free to do other things. Once it starts awaiting your caller can do things until he starts awaiting. Effectively your thread will be fairly free to react on user input. However, this will only be the case if everyone is awaiting. While your thread is busy doing things your thread can't react on user input. Therefore always make sure that if you think your UI thread has to do some busy processing that takes some time use Task.Run and let another thread do it
Another article that helped me: Async-Await by the brilliant explainer Stephen Cleary
This answer deals with the specific case of awaiting an async method in the event handler of a GUI application. In this case the first approach has a significant advantage over the second. Before explaining why, lets rewrite the two approaches in a way that reflects clearly the context of this answer. What follows is only relevant for event handlers of GUI applications.
private async void Button1_Click(object sender, EventArgs args)
{
await Task.Run(async () => await LongProcessAsync());
}
vs
private async void Button1_Click(object sender, EventArgs args)
{
await LongProcessAsync();
}
I added the suffix Async in the method's name, to comply with the guidlines. I also made async the anonymous delegate, just for readability reasons. The overhead of creating a state machine is minuscule, and is dwarfed by the value of communicating clearly that this Task.Run returns a promise-style Task, not an old-school delegate Task intended for background processing of CPU-bound workloads.
The advantage of the first approach is that guarantees that the UI will remain responsive. The second approach offers no such guarantee. As long as you are using the build-in async APIs of the .NET platform, the probability of the UI being blocked by the second approach is pretty small. After all, these APIs are implemented by experts¹. By the moment you start awaiting your own async methods, all guarantees are off. Unless of course your first name is Stephen, and your surname is Toub or Cleary. If that's not the case, it is quite possible that sooner or later you'll write code like this:
public static async Task LongProcessAsync()
{
TeenyWeenyInitialization(); // Synchronous
await SomeBuildInAsyncMethod().ConfigureAwait(false); // Asynchronous
CalculateAndSave(); // Synchronous
}
The problem obviously is with the method TeenyWeenyInitialization(). This method is synchronous, and comes before the first await inside the body of the async method, so it won't be awaited. It will run synchronously every time you call the LongProcessAsync(). So if you follow the second approach (without Task.Run), the TeenyWeenyInitialization() will run on the UI thread.
How bad this can be? The initialization is teeny-weeny after all! Just a quick trip to the database to get a value, read the first line of a small text file, get a value from the registry. It's all over in a couple of milliseconds. At the time you wrote the program. In your PC. Before moving the data folder in a shared drive. Before the amount of data in the database became huge.
But you may get lucky and the TeenyWeenyInitialization() remains fast forever, what about the second synchronous method, the CalculateAndSave()? This one comes after an await that is configured to not capture the context, so it runs on a thread-pool thread. It should never run on the UI thread, right? Wrong. It depends to the Task returned by SomeBuildInAsyncMethod(). If the Task is completed, a thread switch will not occur, and the CalculateAndSave() will run on the same thread that called the method. If you follow the second approach, this will be the UI thread. You may never experience a case where the SomeBuildInAsyncMethod() returned a completed Task in your development environment, but the production environment may be different in ways difficult to predict.
Having an application that performs badly is unpleasant. Having an application that performs badly and freezes the UI is even worse. Do you really want to risk it? If you don't, please use always Task.Run(async inside your event handlers. Especially when awaiting methods you have coded yourself!
¹ Disclaimer, some built-in async APIs are not properly implemented.
Important: The Task.Run runs the supplied asynchronous delegate on a ThreadPool thread, so it's required that the LongProcessAsync has no affinity to the UI thread. If it involves interaction with UI controls, then the Task.Runis not an option. Thanks to #Zmaster for pointing out this important subtlety in the comments.

Not using await Task.Delay(x) (x>0) makes UI thread freeze

I have this function that bruteforces GUIDs to calculate IDs (GUIDs are hash calculations of the ID, so reversing the procedure can't be done by nothing else but bruteforcing through 2^32-1 (yes, that's right) possible IDs.
I used await Task.Delay(1); to "refresh" the UI thread so everything looks natural, however this slows down the process too much, but if I were to use await Task.Delay(0); the whole app would freeze and i wouldn't know the current progress of the search (shown as the 2 IProgresss for the progress bar.
async public Task<Dictionary<string, string>> GetSteamIds(Dictionary<string,string> GUIDs, IProgress<UInt32> progress, IProgress<double> progress2)
{
List<string> Progress = new List<string>();
foreach(string GUID in GUIDs.Keys)
{
Progress.Add(GUID);
}
for (;Iteration <= UInt32.MaxValue;Iteration++)
{
await Task.Delay(0);
string guid = CalculateGUID(MinAcc+Iteration);
if(GUIDs.ContainsKey(guid))
{
GUIDs[guid] = Convert.ToString((Int64)(MinAcc + Iteration));
}
progress.Report(Iteration);
progress2.Report((1.0 * Iteration / UInt32.MaxValue * 100));
if(Progress.Count==0)
{
if (progress2 != null)
{
progress2.Report(100);
}
break;
}
}
return GUIDs;
}
I do not know how to mitigate this and even though my whole method is async, and the call is async, it still sits on the "UI thread" and I don't know how to work around this.
Naturally, I would appreciate a good answer that works, but I would also appreciate some elaboration to how this all works. I've read quite a bit of articles but none really explained it to me in a way for me to understand everything.
Adding the async keyword to a method doesn't actually make the method asynchronous, it just means that you're allowed to use the await keyword inside of the method. You've written an entirely synchronous CPU bound method and just tagged the method as async, making it still just a synchronous CPU bound method, and calling a synchronous CPU bound method from the UI thread is going to block the UI thread, preventing other UI actions from taking place.
Adding in an await Task.Delay(1) is making your method still do all of its long running CPU bound work in the UI thread, it's just stopping every once in a while to move to the end of the line, allowing other operations to run. Not only is this slowing down your work, it also means that the UI thread isn't able to perform other UI operations the vast majority of the time as this process is using up so much of its time.
The solution is to simply not do the long running CPU bound work in the UI thread at all, and to offload that work to another thread.
Since this method of your isn't actually asynchronous, you should remove the async keyword from the method (and change the return type accordingly). When you call this method, if you happen to need to do so from the UI thread, simply wrap it in a call to Task.Run which will offload it to a thread pool thread. If that UI operation need to do work after it has completed with the result, then that UI operation can await the result of Task.Run, and that method should be marked as async, because it really is doing its work asynchronously.
Your GetSteamIds method is entirely synchronous and CPU-bound, so it should have a synchronous signature:
public Dictionary<string, string> GetSteamIds(Dictionary<string,string> GUIDs, IProgress<UInt32> progress, IProgress<double> progress2);
Now, when you want to invoke this (synchronous, CPU-bound) method from the UI thread, use await Task.Run to run it on a threadpool thread and (asynchronously) get the result of the method:
var results = await Task.Run(() => GetSteamIds(guids, progress, progress2));
If you're using Progress<T>, then it will take care of handling progress updates on the UI thread for you; there's no need for the awkward Dispatcher or Control.Invoke.
On a side note, with a very tight CPU-bound loop like this, you may find your progress reports themselves will slow down your UI and degrade your user experience. In that case, consider using my ObservableProgress, an IProgress<T> implementation that throttles progress updates.
Don't run the task on the UI thread.
You could call it like this:
var myTask = Task.Run(() => GetSteamIds(...));
And keep a reference to myTask somewhere so you can test myTask.IsCompleted to see when it's done.
Or, you can use ContinueWith to automatically run some other code when the Task completes. For example:
var myTask = Task.Run(() => GetSteamIds(...)).ContinueWith(() => {
//do something here now that the task is done
}, TaskScheduler.FromCurrentSynchronizationContext());
The TaskScheduler.FromCurrentSynchronizationContext() is to make sure that the continuation code runs on the UI thread (since you will likely want to update the UI with the results).
With this usage, there is no need for your method to be asynchronous at all (it does not need to return Task<>).
Or use BackgroundWorker, as suggested in the comments.
when you call await Task.Delay(1) it will actually give back access to the UI thread because probably the problem is not in the method you are calling, it is in the call of the method.
So you should remove the Task.Delay() in the method and show us the call of the method so we can help you further

Why use Async/await all the way down

I would like to get some clarification on what is the added benefit of using of Await and Async all the way down.
If my application is calling await Func1() (So no blocking to the UI here). and Func1 is calling await Func2(), but the results from Func2() are important for Func1 to complete it's job, then why would I need to make Func2() awaitable. Func1() execution will take just as long because it's waiting on Func2 to finish. All what the await is doing here is adding the StateMachine overhead.
Am I missing something here?
A better slogan is async all the way up. Because you start with an asynchronous operation and make its caller asynchronous and then the next caller etc.
You should use async-await when you have an inherently asynchronous operation (usually I/O but not necessarily) and you don't want to waste a thread idly waiting for the operation to complete. Choosing an async operation instead of a synchronous one doesn't speed up the operation. It will take the same amount of time (or even more). It just enables that thread to continue executing some other CPU bound work instead of wasting resources.
But to be able to await that operation the method needs to be an async one and the caller needs to await it and so forth and so forth.
So async all the way up enables you to actually make an asynchronous call and release any threads. If it isn't async all the way then some thread is being blocked.
So, this:
async Task FooAsync()
{
await Func1();
// do other stuff
}
async Task Func1()
{
await Func2();
// do other stuff
}
async Task Func2()
{
await tcpClient.SendAsync();
// do other stuff
}
Is better than this:
void Foo()
{
Func1();
// do other stuff
}
void Func1()
{
Func2().Wait(); // Synchronously blocking a thread.
// do other stuff
}
async Task Func2()
{
await tcpClient.SendAsync();
// do other stuff
}
The major benefit is the fact that awaiting an asynchronous method returns the worker thread to the pool to be used in other calls (web requests to your .NET MVC web app, for example). The asynchronous work is done on an IO completion thread. When the awaited method finishes, another worker thread will collect the results and resume execution. This prevents worker thread pool exhaustion and allows your application to handle more load (CPU, memory, and network throughput depending).
As for "await all the way down", that seems like an issue to me. Typically await is associated to an external resource (DB call, HTTP request, etc.) that your application must wait on. If you await code that doesn't have external IO dependencies, you're creating overhead that isn't needed. It's possible to have multiple awaits in an async method chain, but awaiting some code that itself calls await but has no other external IO dependency is not good and will just add callback/compiler overhead.
Usually, the reasoning behind async/await goes the other way around:
For whatever reason, you decide that Func2 would be easier to write using await. So you simplify the method by adding the desired awaits, meaning you also have to change the method signature (it will now include the async keyword and a return type of Task or Task<T>).
Because the return type has changed, you can no longer call Func2 like you used to (var result = Func2();), so you're now required to change the calling method, Func1. The easiest way to adapt Func1 will often be to make it async too, and await Func2().
Then, for the same reason (changed signature), you will need to change all calls to Func1, and so on until you get to some kind of entry point (either a UI event handler, or your Main method, or something else).
So you don't start making the "outermost" method async and follow through to the "inner" (called) methods; you usually make things async while going in the opposite direction (from the "innermost" methods back to the calling ones). This other answer calls this idea "async all the way up".
"This async method lacks 'await' operators and will run synchronously" is what happens if you don't await an async method. To harness the benefits of an async method you must await it, turning the caller into an async method which can be awaited etc etc.
From the flow diagram you see that the async method returns a Task (a promise of work to be completed in the future) and yields control to it's caller. The caller can then get on with work not dependent on this result in the meantime. Clearly this needs to bubble up the call stack to find all of this gainful work that can be done without the result (In a UI app this work would include unblocking the UI, which is why it's async all the way up to the the event handler in the below example).
From my initial misreading. So you've found some async code that you need to call, is it worth the async await pattern spreading up your code:
I've heard a lot that the main problem with async-await is it's a much too easy syntax for what it actually does. Program flow gets complicated. I really like async-await, but unfortunately in most the async code I've seen it isn't worth it and is just needlessly ruining my call-stack.
A good thing to keep in mind is the 50ms rule.
"This is the rule that Microsoft followed with the WinRT APIs; anything taking less than 50ms is considered “fast” and close enough to “immediate” that they do not require an asynchronous API."
This is being used in the context of encouraging async-await. However, I think it equally should be applied to tell developers using async-await for essentially immediate functionality to cut it out.
In a UI based application async await provides a very succinct way to handle asynchronous calls resulting in UI updates. If the 'top level' handler from the UI is awaiting a result then there is potentially no real benefit in the whole chain down doing the same unless it makes sense to do so. A design goal of async await was to make async programming look more synchronous and continuous and not have callbacks scattered around etc - making async coding more assessable. It's not something you need to use everywhere arbitrarily.

Categories