UPDATE The purpose of this question is to get a simple answer about Task.Run()
and deadlocking. I very much understand the theoretical reasoning for not mixing async and sync, and I take them to heart. I'm not above learning new things from others; I seek to do that whenever I can. There's just times when all a guy needs is a technical answer...
I have a Dispose()
method that needs to call an async method. Since 95% of my code is async, refactoring isn't the best choice. Having an IAsyncDisposable
(among other features) that's supported by the framework would be ideal, but we're not there yet. So in the mean time, I need to find a reliable way to call async methods from a synchronous method without deadlocking.
I'd prefer not to use ConfigureAwait(false)
because that leaves the responsibility scattered all throughout my code for the callee to behave a certain way just in case the caller is synchronous. I'd prefer to do something in the synchronous method since it's the deviant bugger.
After reading Stephen Cleary's comment in another question that Task.Run()
always schedules on the thread pool even async methods, it made me think.
In .NET 4.5 in ASP.NET or any other synchronization context that schedules tasks to the current thread / same thread, if I have an asynchronous method:
private async Task MyAsyncMethod()
{
...
}
And I want to call it from a synchronous method, can I just use Task.Run()
with Wait()
to avoid deadlocks since it queues the async method the the thread pool?
private void MySynchronousMethodLikeDisposeForExample()
{
// MyAsyncMethod will get queued to the thread pool
// so it shouldn't deadlock with the Wait() ??
Task.Run((Func<Task>)MyAsyncMethod).Wait();
}
MyAsyncMethod()
is marshaling back to the calling context, presumably it actually needs to execute in that context or it won't work. Fundimentally you should avoid this problem entirely. Either make the program synchronous, or make it asynchronous. Doing half and half is only going to cause problems. – LewseDispose
method is at least concerning. – LewseTask.Run()
to avoid deadlocks will work reliably. Like I said 95% of my code is async. There's still places in the .NET that don't support async. I try to eliminate the synchronous code wherever I can and when time allows, but ultimately I end up needing to call asynchronous code from synchronous code. – Vainusing
/IDispose
is just tiny amount of syntactic sugar asynchronous creating helper function likeTask UsingAsync(Func<T> createResource, Action<T> useResource) where T:IDisposeAsync
should produce comparable code... – HundredfoldHttpContext.Current
, blowing up UI updates... – Hundredfold