在ASP.NET 4.5应用程序中,哪些更适合从同步方法调用异步方法?Task.Run vs null SynchronizationContext
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核心外的过滤器和剃须刀的观点不是异步,所以如果我想从过滤器或剃刀视图调用异步方法,我需要以某种方式同步它。由于SynchronizationContext
,只是使用SomethingAsync().GetAwaiter().GetResult()
导致死锁,所以我需要一种方法来运行此代码而不需要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'方法稍微更明显一些,'SynchronizationContext.Current'方法稍微有点高性能。哪一个“更好”纯粹是一个意见问题。 –
我应该说“更好”。好的,所以在我看来,第二种情况没有什么问题,所以如果它包含在一个漂亮的静态函数中,听起来应该很好用 – Marius
你不应该需要'if'检查。 'SetSynchronizationContext(null)'是有效的。 –