首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Task.Run对空SynchronizationContext

Task.Run对空SynchronizationContext
EN

Stack Overflow用户
提问于 2017-02-14 10:05:52
回答 1查看 1.4K关注 0票数 5

在ASP.NET 4.5应用程序中,哪个更适合从同步方法调用异步方法?

代码语言:javascript
复制
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来运行这段代码的方法。

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

代码语言:javascript
复制
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"));
EN

回答 1

Stack Overflow用户

发布于 2017-04-22 20:53:41

显然,同步调用异步代码并不理想,但是如果必须的话,我想说,如果可以帮助的话,请避免使用Task.Run

Task.RunSetSynchronizationContext(null)上有很多问题

  • 还不清楚为什么要使用它,您想在web服务器上启动一个新任务吗?这将被新开发人员快速删除,如果没有评论。然后是繁荣,很难诊断生产问题(死锁)。
  • 它在一个新的线程池线程上启动,直到它到达第一个等待完成的继续,vs同步运行时才需要启动。(这是一个非常小的优化)
  • 如果您从多个级别执行此操作以保护您的SynchronizationContext,那么它会使您为整个任务返回函数同步阻塞,而不仅仅是需要它的区域,每次使用它时,您也会将问题增加一倍。您将以更长的阻塞异步代码而告终,这肯定不是您想要的。
  • 如果发现在您认为有阻塞/死锁的地方没有阻塞/死锁,或者后来修复了,那么Task.Run现在正在引入阻塞而不是异步,而SetSynchronizationContext(null)不会花费任何代价。

最后,当您阻塞一个 (Stephen Toub)返回函数时,另一个建议是使用Task。它以这样一种方式等待:排队的连续进程由阻塞线程运行,这样您就不用支付多个并发线程的代价,并且没有死锁,显然仍然不如一直使用异步。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42223162

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档