I'm trying to understand await and async.
It works very well. But now I have a deadlock.
I've called ConfigureAwait with false, like in this article, but my code is still blocking.
Here's a little snippet of my code:
private void button1_Click(object sender, EventArgs e)
{
var result = HeavyWorkAsync().Result;
richTextBox1.AppendText(result);
}
private string HeavyWork()
{
for (var index = 0; index < 1000; index++)
{
Task.Delay(10).Wait();
}
return "finished";
}
private async Task<string> HeavyWorkAsync()
{
var task = await Task.Factory.StartNew<string>(HeavyWork).ConfigureAwait(false);
return task;
}
What's blocking is not the task itself, it's the call to Result. A Task represents an asynchronous operation, but calling its Result property, or calling Wait() will block the current thread until the method returns. And in a lot of cases, it will cause a deadlock because the task is not able to complete with it's calling thread blocked!
To prevent that, chain the tasks asynchronously, using async and await
private async void button1_Click(object sender, EventArgs e)
{
var result = await HeavyWorkAsync(); // <=== await
richTextBox1.AppendText(result);
}
Also, Task.Delay(10).Wait(); completely defeats the prupose of using tasks in the first place: that will block the current thread. If that's really what you want to do (and it's pretty unlikely), call Thread.Sleep(10);instead, it will make your intent much clearer, and you will have less hoops to jump through. Or better, use await Task.Delay(10);in an async method.
About ConfigureAwait
What exactly does ConfigureAwait(false) do?
It removes the obligation for the continuation of the task to run in the same context as the caller of the task. In most cases that means that the continuation is no longer guaranteed to run on the same context. So if I have a method thad does Foo(), waits a little then Bar() like this one:
async Task DoStufAsync()
{
Foo();
await Task.Delay(10);
Bar(); // run in the same context as Foo()
}
I'm guaranteed Bar will run in the same context. If I had ConfigureAwait(false), it's no longer the case
async Task DoStufAsync()
{
Foo();
await Task.Delay(10).ConfigureAwait(false);
Bar(); // can run on another thread as Foo()
}
When you're using ConfigureAwait(false), you tell your program you dont mind about the context. It can solve some deadlocking problems, but isn't usually the right solution. The right solution is most likely never to wait for tasks in a blocking way, and being asynchronous all the way.
To expand upon Falanwe's answer, you should check out Stephen Cleary's blog post. Based off of the code I'm assuming that you are using a Windows Forms application, so a call to Task.Result will execute the task on the UI context, which in turn blocks the UI thread.
Related
This question is for learning purposes. I am not in developing anything for sure.
I have two long running CPU-bound operations (JobA and JobB). Both do not interact with the GUI. Unlike Task.FromResult that completes immediately at the await expression, my Task.Run(()=>JobA()).ConfigureAwait(false) will return control to the caller and causes the continuation to be executed in non-GUI thread (because of ConfigureAwait(false)).
static void JobA()
{
for (int i = 0; i < int.MaxValue; i++) ;
}
static void JobB()
{
for (int i = 0; i < int.MaxValue; i++) ;
}
private static async Task Async()
{
await Task.Run(()=>JobA()).ConfigureAwait(false);
JobB();
//await Task.Run(() => JobB());
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
await Async();
}
Question
In my understanding, wrapping JobB with Task.Run as in the second case below is unnecessary because the continuation is already guaranteed to run in non-GUI thread.
private static async Task Async()
{
await Task.Run(()=>JobA()).ConfigureAwait(false);
JobB();
}
private static async Task Async()
{
await Task.Run(()=>JobA()).ConfigureAwait(false);
await Task.Run(() => JobB());
}
Exception behavior in asynchronous is a bit tricky so I am asking this question because I want to know whether eliding is risky when exception occurs. If there is no such risk, I will delete this question.
my Task.Run(()=>JobA()).ConfigureAwait(false) will return control to the caller and causes the continuation to be executed in non-GUI thread (because of ConfigureAwait(false))
Really? Are you sure?
One interesting aspect of await is that it behaves synchronously if possible. So if the task has already completed by the time await checks it, then await will continue running synchronously. In this scenario, ConfigureAwait has no effect.
Notably, this can happen when you have different computers with different CPU speeds, or memory available, or cache behavior. With a dose of Murphy's Law, you end up with a production issue that you can't reproduce, which is always fun.
So, I never rely on ConfigureAwait(false) to guarantee that any code is running on a thread pool thread. That's what Task.Run is for. For the simple case you posted, you can do one job after another within the Task.Run: await Task.Run(() => { JobA(); JobB(); });
In my current project, I have a piece of code that, after simplifying it down to where I'm having issues, looks something like this:
private async Task RunAsync(CancellationToken cancel)
{
bool finished = false;
while (!cancel.IsCancellationRequested && !finished)
finished = await FakeTask();
}
private Task<bool> FakeTask()
{
return Task.FromResult(false);
}
If I use this code without awaiting, I end up blocking anyway:
// example 1
var task = RunAsync(cancel); // Code blocks here...
... // Other code that could run while RunAsync is doing its thing, but is forced to wait
await task;
// example 2
var task = RunAsync(cancelSource.Token); // Code blocks here...
cancelSource.Cancel(); // Never called
In the actual project, I'm not actually using FakeTask, and there usually will be some Task.Delay I'm awaiting in there, so the code most of the time doesn't actually block, or only for a limited amount of iterations.
In unit testing, however, I'm using a mock object that does pretty much do what FakeTask does, so when I want to see if RunAsync responds to its CancellationToken getting cancelled the way I expect it to, I'm stuck.
I have found I can fix this issue by adding for example await Task.Delay(1) at the top of RunAsync, to force it to truly run asynchronous, but this feels a bit hacky. Are there better alternatives?
You have an incorrect mental picture of what await does. The meaning of await is:
Check to see if the awaitable object is complete. If it is, fetch its result and continue executing the coroutine.
If it is not complete, sign up the remainder of the current method as the continuation of the awaitable and suspend the coroutine by returning control to the caller. (Note that this makes it a semicoroutine.)
In your program, the "fake" awaitable is always complete, so there is never a suspension of the coroutine.
Are there better alternatives?
If your control flow logic requires you to suspend the coroutine then use Task.Yield.
Task.FromResult actually runs synchronously, as would await Task.Delay(0). If you want to actually simulate asynchronous code, call Task.Yield(). That creates an awaitable task that asynchronously yields back to the current context when awaited.
As #SLaks said, your code will run synchronously. One thing is running async code, and another thing is running parallel code.
If you need to run your code in parallel you can use Task.Run.
class Program
{
static async Task Main(string[] args)
{
var tcs = new CancellationTokenSource();
var task = Task.Run(() => RunAsync("1", tcs.Token));
var task2 = Task.Run(() => RunAsync("2", tcs.Token));
await Task.Delay(1000);
tcs.Cancel();
Console.ReadLine();
}
private static async Task RunAsync(string source, CancellationToken cancel)
{
bool finished = false;
while (!cancel.IsCancellationRequested && !finished)
finished = await FakeTask(source);
}
private static Task<bool> FakeTask(string source)
{
Console.WriteLine(source);
return Task.FromResult(false);
}
}
C#'s async methods execute synchronously up to the point where they have to wait for a result.
In your example there is no such point where the method has to wait for a result, so the loop keeps running forever and thereby blocking the caller.
Inserting an await Task.Yield() to simulate some real async work should help.
There is such application:
static void Main(string[] args)
{
HandleRequests(10).Wait();
HandleRequests(50).Wait();
HandleRequests(100).Wait();
HandleRequests(1000).Wait();
Console.ReadKey();
}
private static async Task IoBoundWork()
{
await Task.Delay(100);
}
private static void CpuBoundWork()
{
Thread.Sleep(100);
}
private static async Task HandleRequest()
{
CpuBoundWork();
await IoBoundWork();
}
private static async Task HandleRequests(int numberOfRequests)
{
var sw = Stopwatch.StartNew();
var tasks = new List<Task>();
for (int i = 0; i < numberOfRequests; i++)
{
tasks.Add(HandleRequest());
}
await Task.WhenAll(tasks.ToArray());
sw.Stop();
Console.WriteLine(sw.Elapsed);
}
Below the output of this app:
From my perspective having CPU-bound and IO-bound parts in one method it is quite regular situation, e.g. parsing/archiving/serialization of some object and saving that to the disk, so it should probably work well. However in the implementation above it works very slow. Could you please help me to understand why?
If we wrap the body of CpuBoundWork() in Task it significantly improve performance:
private static async Task CpuBoundWork()
{
await Task.Run(() => Thread.Sleep(100));
}
private static async Task HandleRequest()
{
await CpuBoundWork();
await IoBoundWork();
}
Why it works so slow without Task.Run? Why we can see performance boost after adding Task.Run? Should we always use such approach in similar methods?
for (int i = 0; i < numberOfRequests; i++)
{
tasks.Add(HandleRequest());
}
The returned task is created at the first await in the HandleRequest(). So you are executing all CPU bound code on one thread: the for loop thread. complete serialization, no parallelism at all.
When you wrap the CPU part in a task you are actually submitting the CPU part as Tasks, so they are executed in parallel.
The way you're doing, this is what happens:
|-----------HandleRequest Timeline-----------|
|CpuBoundWork Timeline| |IoBoundWork Timeline|
Try doing it like this:
private static async Task HandleRequest()
{
await IoBoundWork();
CpuBoundWork();
}
It has the advantage of starting the IO work and while it waits, the CpuBoundWork() can do the processing. You only await at the last moment you need the response.
The timeline would look somewhat like this:
|--HandleRequest Timeline--|
|Io...
|CpuBoundWork Timeline|
...BoundWork Timeline|
On a side note, open extra threads (Task.Run) with caution in an web environment, you already have a thread per request, so multiplying them will have a negative impact on scalability.
You've indicated that your method ought to be asynchronous, by having it return a Task, but you've not actually made it (entirely) asynchronous. You're implementation of the method does a bunch of expensive, long running, work synchronously, and then returns to the caller and does some other work asynchronously.
Your callers of the method, however, assume that it's actually asynchronous (in entirety) and that it doesn't do expensive work synchronously. They assume that they can call the method multiple times, have it return immediately, and then continue on, but since your implementation doesn't return immediately, and instead does a bunch of expensive work before returning, that code doesn't work properly (specifically, it's not able to start the next operation until the previous one returns, so that synchronous work isn't being done in parallel).
Note that your "fix" isn't quite idiomatic. You're using the async over sync anti-pattern. Rather than making CpuBoundWork async and having it return a Task, despite being a CPU bound operation, it should remain as is an HandleRequest should handle indicating that the CPU bound work should be done asynchronously in another thread by calling Task.Run:
private static async Task HandleRequest()
{
await Task.Run(() => CpuBoundWork());
await IoBoundWork();
}
Lets say I have a method defined as follows:
public async Task CreateUser()
{
await GetUserDetails();
GetUserOrder();
}
private void GetUserDetails() {
private void GetUserOrder() {
Does the method GetUserDetails(); and GetUserOrder() have to be async as well to avoid UI blocking ?
I cannot await the GetUserDetails() method since it is not async. How can I achieve this in c# ? I want to ensure all these methods are invoked step by step.
The relevant question is in a comment:
How can I ensure all my methods are invoked completely sequentially?
The fact that you're asking the question indicates that you don't understand what "await" is. Await is the sequencing operation on a asynchronous workflows. An await means this workflow will not proceed until the awaited task is complete. It's an asynchronous wait, hence the name await.
Consider this question: in a synchronous workflow, what is the sequencing operation?
No, really, give it some thought.
.
.
.
It is ;. When you say
fResult = foo();
bResult = bar();
qResult = qux();
that means that foo has to finish completely before bar can begin. That is not true for asynchronous workflows. If we have
fTask = fooAsync();
bTask = barAsync();
qTask = quxAsync();
Then the asynchronous operations can complete in any order. If we say
await fooAsync();
await barAsync();
await quxAsync();
Then barAsync will not start until fooAsync's task completes. await sequences the asynchronous workflow. The difference is that the thread can continue to do other unrelated work while asynchronously waiting for foo to complete, which is not true in a synchronous workflow; in a synchronous workflow the thread is already busy computing the foo result, so it can't do other work.
yes if you want to wait than you have to write await for that methods also. because after first await your code agian will be synchronous ..and if UI thread than it will run on it.
1.you code will be , so by this code you code become asynchronous for GetUserORder also. you just have to wrap method in Task construct and return
public async Task CreateUser()
{
await GetUserDetails();
await Task.Factory.SartNew(()=> GetUserOrder());
}
2.or you can do this also
public async Task CreateUser()
{
await Task.Factory.SartNew(()=>{
GetUserDetails();
GetUserOrder(); });
}
3.or you can do like this also, in below code will not wait for getuserorder method and excute await one method
public async Task CreateUser()
{
Task.Factory.SartNew(()=> GetUserOrder()).ContinueWith((t)=> Console.WriteLine("Completed");
await GetUserDetails();
}
4.or last one variation, here you start GetUserOrder first and dont wait for it than you call GetUserDetails in async fashion , and if you want to work on GetUserOrder method want to wait just use Wait method.
public async Task CreateUser()
{
var task = Task.Factory.SartNew(()=> GetUserOrder());
await GetUserDetails();
if(!task.IsCompleted)
task.Wait();
}
in your case you can go for 3 and if you want to wait go for 4th one.
As you asked me in comment what is difference between Task.Run and statnew method -: for that you can check this SO question : Regarding usage of Task.Start() , Task.Run() and Task.Factory.StartNew()
You should put await only in front of async methods. To run a synchronous one that you don't want to wait, you can use a new thread from the tread pool:
new Thread(() => DoSomething()).Start();
or
Task.Factory.SartNew(()=> DoSomething());
Here is the help page: https://msdn.microsoft.com/en-us/library/dd321439(v=vs.110).aspx
Otherwise, your call to GetUserDetails will have to finish before you execute the next line.
I have a method that is defined as
public async Task SomeAsyncMethod()
{
DoSomeStuff();
await Task.Run(() => {
DoSomeSyncStuff();
DoSomeOtherSyncStuff();
});
var someDebugVariable = "someDebugValue";
}
The method itself does exactly what it is supposed to do and everything runs fine. Yet ... it looks like the "outer" async Task never completes.
Example: When I call it like this
public void CallerMethod()
{
Task t = SomeAsyncMethod();
t.Wait();
}
the t.Wait() never completes. Furthermore: if I place a breakpoint at the assignment of someDebugVariable it never gets hit.
I might add that DoSomeSyncStuff and DoSomeOtherSyncStuff really do what they are supposed to and debugging through them tells me that they both complete.
To prove my point I modified my method like this, and the results are still the same.
public async Task SomeAsyncMethod()
{
DoSomeStuff();
await Task.Run(() => {
/*
DoSomeSyncStuff();
DoSomeOtherSyncStuff();
*/
var a = 2; var b = 3; var c = a + b;
});
var someDebugVariable = "someDebugValue";
}
EDIT
I have tried removing everything but the await Task.Run and it does not change anything. It still does not complete.
The application is a WPF application. The caller thread is the UI thread.
What am I missing here?
The t.Wait() call is causing a deadlock, and also makes the async call entirely pointless. I believe if you change the code to
await Task.Run(() => {
// ...
}).ConfigureAwait(false);
You can fix the deadlock and let the code proceed, but you should really get rid of the t.Wait() call. Anything that needs to be done with the results of the sync function calls should be done after the awaited task, not after the call of the async function.
More in depth:
task.Wait() will block all execution on the main thread while the task is running. When the await task completes, it tries to marshall back to the main thread, but the main thread is blocked! Since A is waiting for B, and B is waiting for A, you get a deadlock.
See: http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html