I found this method in an ASP.NET application:
public void LogoutAllSessions()
{
Task.Run(async () => await _identityHttpClient.GetAsync(Uri)).Wait();
// Could this be rewritten as this:?
// _identityHttpClient.GetAsync(Uri).GetAwaiter().GetResult();
}
Is this just running a task within another task and blocking the thread while it waits for the outer task to finish?
I was told it was written like this because updating it to just use plain async/await would involve changing too many methods up the stack.
Would _identityHttpClient.GetAsync(Uri).GetAwaiter().GetResult(); do the same thing as Task.Run(async () => await _identityHttpClient.GetAsync(Uri)).Wait();?
Would one be faster than the other?
There is indeed a reason to wrap the asynchronous method
GetAsyncinTask.Runbefore waiting it synchronously with.Wait()or.GetAwaiter().GetResult(). The reason is to prevent a deadlock in case theGetAsyncis implemented withasync/await, there is aSynchronizationContextinstalled on the current thread (typical for GUI applications), there is anawaitinside theGetAsyncnot configured with.ConfigureAwait(false), and the awaitable (Task) is not already completed at theawaitpoint. Under these conditions the deadlock happens consistently (withoutTask.Run), you'll observe it immediately during the testing (the application will hang), and you'll be forced to fix it. Wrapping the call withTask.Runis one way to fix it, because theTask.Runinvokes the asynchronous method on theThreadPool, where there is noSynchronizationContextinstalled. If you remove theTask.Runand your application does not hang, most likely theTask.Runis redundant.The effect that a redundant
Task.Runhas on performance is negligible. It can be either beneficial or detrimental, but the difference will be minuscule.To understand the reason for the deadlock, you could take a look at this question: An async/await example that causes a deadlock.