Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'await' works, but calling task.Result hangs/deadlocks

People also ask

What is task deadlock?

Queued tasks are executed one by one. If you block the UI thread there is nothing left to execute tasks and you have a deadlock.

What causes deadlock in C#?

A deadlock in C# is a situation where two or more threads are frozen in their execution because they are waiting for each other to finish. For example, thread A is waiting on lock_1 that is held by thread B. Thread B can't finish and release lock_1 because it waits on lock_2, which is held by thread A.

Does await block execution C#?

The await operator doesn't block the thread that evaluates the async method. When the await operator suspends the enclosing async method, the control returns to the caller of the method.


Acquiring a value via an async method:

var result = Task.Run(() => asyncGetValue()).Result;

Syncronously calling an async method

Task.Run( () => asyncMethod()).Wait();

No deadlock issues will occur due to the use of Task.Run.


You're running into the standard deadlock situation that I describe on my blog and in an MSDN article: the async method is attempting to schedule its continuation onto a thread that is being blocked by the call to Result.

In this case, your SynchronizationContext is the one used by NUnit to execute async void test methods. I would try using async Task test methods instead.


You can avoid deadlock adding ConfigureAwait(false) to this line:

IRestResponse<DummyServiceStatus> response = await restResponse;

=>

IRestResponse<DummyServiceStatus> response = await restResponse.ConfigureAwait(false);

I've described this pitfall in my blog post Pitfalls of async/await


You are blocking the UI by using Task.Result property. In MSDN Documentation they have clearly mentioned that,

"The Result property is a blocking property. If you try to access it before its task is finished, the thread that's currently active is blocked until the task completes and the value is available. In most cases, you should access the value by using Await or await instead of accessing the property directly."

The best solution for this scenario would be to remove both await & async from methods & use only Task where you're returning result. It won't mess your execution sequence.


If you don't get any callbacks or the control hangs up, after calling the service/API async function, you have to configure Context to return a result on the same called context.

Use TestAsync().ConfigureAwait(continueOnCapturedContext: false);

You will be facing this issue only in web applications, but not in static void main.