I don't quite understand the difference between Task.Wait
and await
.
I have something similar to the following functions in a ASP.NET WebAPI service:
public class TestController : ApiController
{
public static async Task<string> Foo()
{
await Task.Delay(1).ConfigureAwait(false);
return "";
}
public async static Task<string> Bar()
{
return await Foo();
}
public async static Task<string> Ros()
{
return await Bar();
}
// GET api/test
public IEnumerable<string> Get()
{
Task.WaitAll(Enumerable.Range(0, 10).Select(x => Ros()).ToArray());
return new string[] { "value1", "value2" }; // This will never execute
}
}
Where Get
will deadlock.
What could cause this? Why doesn't this cause a problem when I use a blocking wait rather than await Task.Delay
?
This question is related to
c#
task-parallel-library
deadlock
async-await
Some important facts were not given in other answers:
"async await" is more complex at CIL level and thus costs memory and CPU time.
Any task can be canceled if the waiting time is unacceptable.
In the case "async await" we do not have a handler for such a task to cancel it or monitoring it.
Using Task is more flexible then "async await".
Any sync functionality can by wrapped by async.
public async Task<ActionResult> DoAsync(long id)
{
return await Task.Run(() => { return DoSync(id); } );
}
"async await" generate many problems. We do not now is await statement will be reached without runtime and context debugging. If first await not reached everything is blocked. Some times even await seems to be reached still everything is blocked:
https://github.com/dotnet/runtime/issues/36063
I do not see why I'm must live with the code duplication for sync and async method or using hacks.
Conclusion: Create Task manually and control them is much better. Handler to Task give more control. We can monitor Tasks and manage them:
https://github.com/lsmolinski/MonitoredQueueBackgroundWorkItem
Sorry for my english.
Based on what I read from different sources:
An await
expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async
method as a continuation on the awaited task. Control then returns to the caller of the async
method. When the task completes, it invokes its continuation, and execution of the async
method resumes where it left off.
To wait for a single task
to complete, you can call its Task.Wait
method. A call to the Wait
method blocks the calling thread until the single class instance has completed execution. The parameterless Wait()
method is used to wait unconditionally until a task completes. The task simulates work by calling the Thread.Sleep
method to sleep for two seconds.
This article is also a good read.
Source: Stackoverflow.com