在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"));发布于 2017-04-22 20:53:41
显然,同步调用异步代码并不理想,但是如果必须的话,我想说,如果可以帮助的话,请避免使用Task.Run。
Task.Run在SetSynchronizationContext(null)上有很多问题
SynchronizationContext,那么它会使您为整个任务返回函数同步阻塞,而不仅仅是需要它的区域,每次使用它时,您也会将问题增加一倍。您将以更长的阻塞异步代码而告终,这肯定不是您想要的。Task.Run现在正在引入阻塞而不是异步,而SetSynchronizationContext(null)不会花费任何代价。最后,当您阻塞一个 (Stephen Toub)返回函数时,另一个建议是使用Task。它以这样一种方式等待:排队的连续进程由阻塞线程运行,这样您就不用支付多个并发线程的代价,并且没有死锁,显然仍然不如一直使用异步。
https://stackoverflow.com/questions/42223162
复制相似问题