Reputation: 4428
I'm using Microsoft's AsyncHelper
(source) to call an async method from a synchronous context. This works just fine:
Result r = AsyncHelper.RunSync(async () => await SomeClass.SomeMethodAsync());
However, if I extract the Task and then try to run this extracted task synchronously instead, I encounter a deadlock.:
Task<Result> t = SomeClass.SomeMethodAsync();
Result r = AsyncHelper.RunSync(async () => await t);
Why does this happen, and what can be done to make this run?
Upvotes: 1
Views: 310
Reputation: 456417
AsyncHelper.RunSync
uses the thread pool hack to ensure that its delegate is called without a context, thus making it safe to block on (assuming that the delegate is safe to be called on a thread pool thread). In your code, SomeMethodAsync
is executed on a thread pool thread, so any await
s will not capture a context.
what can be done to make this run?
Well, you would use the first code sample instead of the second.
If you want to have a construct that represents some code to run, then you should use a delegate type such as Func<Task<T>>
. E.g.:
Func<Task<Result>> func = () => SomeClass.SomeMethodAsync();
Result r = AsyncHelper.RunSync(func);
With asynchronous code, Task<T>
does not represent some code to run; it represents some code that has already started. Use Func<Task<T>>
to represent some code to run.
Upvotes: 3