在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)'是有效的。 –