Mar*_*ius 5 c# asp.net asp.net-mvc asynchronous razor
在 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);
}
Run Code Online (Sandbox Code Playgroud)
注意:是的,我知道我应该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"));
Run Code Online (Sandbox Code Playgroud)
显然,同步调用异步代码并不理想,但是如果您必须这样做,我会说Task.Run如果您可以帮助的话就避免这样做。
Task.Run有很多问题SetSynchronizationContext(null):
SynchronizationContext系统,那么您会同步阻塞整个任务返回函数,而不仅仅是需要它的区域,那么每次使用它时您的问题也会成倍增加。您最终会在异步代码上遇到更长的阻塞,这当然不是您想要的。Task.Run现在正在引入异步阻塞,而SetSynchronizationContext(null)不会花费您任何费用。最后,一个替代建议是当您阻止返回函数时使用类似AsyncPump.Run(Stephen Toub)Task的东西。它以这样一种方式等待,即排队的延续由阻塞线程运行,这样您就不必付出多个并发线程的代价,并且不会出现死锁,显然仍然不如一直使用异步好。
| 归档时间: |
|
| 查看次数: |
1584 次 |
| 最近记录: |