I have a method Task DoWork():
public Task DoWork() => Call();
private async Task Call()
{
await DoAnotherWorkAsync()
}
Then I use this method in another part of the project like this:
public void Execute(ref param1, ref param2)
{
...
someInstance.DoWork().Wait();
}
And it doesn't work (just waiting too long). But the following code is working pretty correctly:
public void Execute(ref param1, ref param2)
{
...
Task.Run(async => await someInstance.DoWork()).Wait();
}
Can anyone explain this behavior and suggest how to fix it? Thanks.
CodePudding user response:
As explained in my blog post Don't Block on Async Code, the Wait()
is probably causing a deadlock. This deadlock will happen when there is 1) a single-threaded context captured by an await
, and 2) blocking code (Wait()
) further up that call stack.
The reason the Task.Run
works is that the delegate is run on a thread pool thread, which does not have a single-threaded context.
The best solution is not to block at all.
If this is a UI app, then use a different UX pattern (e.g., show a "loading..." or "executing..." indicator while the asynchronous work is being done, and then update the UI when it is complete). Blocking the UI thread is considered poor UX (and may cause rejection from app stores if this is a mobile app).
If this is a server-side app, then use await
instead of blocking and let async
/await
propagate up all the way.