asp.net - 在MVC路由中使用 “async”(即使应该完成)也会使路由死锁;如何避免这种情况?

标签 asp.net .net asp.net-mvc asynchronous task-parallel-library

考虑以下内容(基于默认的MVC模板),它是后台发生的某些“填充”的简化版本-可以很好地完成并显示预期结果20:

public ActionResult Index()
{
    var task = SlowDouble(10);
    string result;
    if (task.Wait(2000))
    {
        result = task.Result.ToString();
    }
    else
    {
        result = "timeout";
    }

    ViewBag.Message = result;
    return View();
}
internal static Task<long> SlowDouble(long val)
{
    TaskCompletionSource<long> result = new TaskCompletionSource<long>();
    ThreadPool.QueueUserWorkItem(delegate
    {
        Thread.Sleep(50);
        result.SetResult(val * 2);
    });
    return result.Task;
}

但是,现在,如果我们在混合中添加一些async:
public static async Task<long> IndirectSlowDouble(long val)
{
    long result = await SlowDouble(val);

    return result;
}

并将路线的第一行更改为:
var task = IndirectSlowDouble(10);

然后不起作用;它超时了。如果我们添加断点,则return result;方法中的async仅在路由完成之后才会发生-基本上,看来系统不愿意使用任何线程来继续async操作,直到请求完成为止。更糟糕的是:如果我们使用了.Wait()(或访问了.Result),那么它将完全死锁。

那么:那是什么?明显的解决方法是“不涉及async”,但这在使用库等时并不容易。最终,SlowDoubleIndirectSlowDouble之间没有功能上的差异(尽管存在明显的结构差异)。

注意:在console / winform / etc中完全一样的东西可以正常工作。

最佳答案

这与在ASP.NET(.NET 4.5之前)中实现同步上下文的方式有关。关于此行为有很多问题:

Task.WaitAll hanging with multiple awaitable tasks in ASP.NET

Asp.net SynchronizationContext locks HttpApplication for async continuations?

在ASP.NET 4.5中,本文介绍了同步上下文的新实现。

http://blogs.msdn.com/b/webdev/archive/2012/11/19/all-about-httpruntime-targetframework.aspx

关于asp.net - 在MVC路由中使用 “async”(即使应该完成)也会使路由死锁;如何避免这种情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13621647/

相关文章:

asp.net - Dynatrace 和 iis 问题

asp.net - 为什么我的 ASP.NET 单点登录停止工作?

c# - 错误无法评估表达式,因为代码已优化

.net - 使用 Azure 网站时出现定期 ServiceBus 错误 "The X.509 certificate CN=servicebus.windows.net is not in the trusted people store"

asp.net-mvc - 如何从自定义 ModelBinder 中调用 UpdateModel? (MVC)

asp.net - 您如何在 ASP.NET 解决方案中调用物理上分离的 UI/BL 代码?

c# - 缺少 DLL 和引用的问题

c# - ASP.Net Web 应用程序中的随机高 JIT 时间

c# - 在 .NET Framework 中获取国家代码

asp.net-mvc - 使用 Ninject 设置服务