gpt4 book ai didi

c# - Task.Run 与 null SynchronizationContext

转载 作者:行者123 更新时间:2023-11-30 17:34:36 25 4
gpt4 key购买 nike

在 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 中,过滤器和 razor View 不是异步的,所以如果我想从过滤器或 razor View 调用异步方法,我需要以某种方式同步它。由于 SynchronizationContext,仅使用 SomethingAsync().GetAwaiter().GetResult() 会导致死锁,因此我需要一种无需 即可运行此代码的方法>同步上下文

编辑这是一个简单的帮助器类,它干净地包装了它:

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.RunSetSynchronizationContext(null) 方面有很多问题:

  • 不清楚您为什么要使用它,您想在网络服务器上开始一个新任务吗?如果没有评论,这将被新开发人员快速删除。然后是繁荣,难以诊断生产问题(死锁)。
  • 它在不需要时在一个新的线程池线程上启动,直到它到达第一个等待完成的延续,而不是同步运行。 (这是一个非常小的优化)
  • 如果您从多个级别执行此操作以保护您的 SynchronizationContext,它会让您同步阻塞整个任务返回函数,而不仅仅是需要它的区域,您还会将每个问题都乘以你使用它的时间。您最终会更长阻塞异步代码,这当然不是您想要的。
  • 如果事实证明在您认为存在的地方没有阻塞/死锁,或者它随后被修复,Task.Run 现在引入阻塞而不是异步,而 SetSynchronizationContext(null ) 不会花费您任何费用。

最后,另一个建议是 use something like AsyncPump.Run (Stephen Toub)当您阻塞 Task 返回函数时。它以排队的延续由阻塞线程运行的方式等待,这样你就不用为多个并发线程付出代价,也不会出现死锁,显然仍然不如一直使用异步好。

关于c# - Task.Run 与 null SynchronizationContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42223162/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com