![](/img/trans.png)
[英]SynchronizationContext flows on Task.Run but not on await
[英]Task.Run vs null SynchronizationContext
在ASP.NET 4.5应用程序中,哪一个更适合从同步方法调用异步方法?
var result = Task.Run(() => SomethingAsync()).GetAwaiter().GetResult();
// or
var temp = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(null);
return SomethingAsync().GetAwaiter().GetResult();
}
finally
{
SynchronizationContext.SetSynchronizationContext(temp);
}
注意:是的,我知道我应该使用async/await
一直向下,但我问的是最底层,在ASP.NET Core之外,过滤器和剃刀视图不是异步的,所以如果我想调用从过滤器或剃刀视图的异步方法,我需要以某种方式同步它。 只是使用SomethingAsync().GetAwaiter().GetResult()
导致死锁,因为SynchronizationContext
,所以我需要一种方法来运行没有SynchronizationContext
代码。
编辑这是一个简单的帮助类,它干净地包装它:
public static class Async
{
public static T Run<T>(Func<Task<T>> func)
{
var context = SynchronizationContext.Current;
if (context == null)
{
return func().GetAwaiter().GetResult();
}
SynchronizationContext.SetSynchronizationContext(null);
try
{
return func().GetAwaiter().GetResult();
}
finally
{
SynchronizationContext.SetSynchronizationContext(context);
}
}
public static void Run(Func<Task> func)
{
var context = SynchronizationContext.Current;
if (context == null)
{
func().GetAwaiter().GetResult();
return;
}
SynchronizationContext.SetSynchronizationContext(null);
try
{
func().GetAwaiter().GetResult();
}
finally
{
SynchronizationContext.SetSynchronizationContext(context);
}
}
}
// Example
var result = Async.Run(() => GetSomethingAsync("blabla"));
显然,同步调用异步代码并不理想,但如果你必须我会说如果你可以帮助它,请避免使用Task.Run
。
Task.Run
比SetSynchronizationContext(null)
有许多问题:
SynchronizationContext
它会使您同步阻止整个任务返回功能,而不仅仅是需要它的区域,每次使用它时,您也会倍增您的问题。 您最终会对异步代码进行更长时间的阻止,这肯定不是您想要的。 Task.Run
现在正在引入阻塞异步,而SetSynchronizationContext(null)
将不会花费你任何东西。 最后,另一个建议是在阻止Task
返回功能时使用AsyncPump.Run
(Stephen Toub)之类的东西 。 它以阻塞线程运行排队延续的方式等待,这样你就不会支付多个并发线程的价格而且没有死锁,显然仍然没有像一直使用异步一样好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.