如何监控 MVC4 中的异步/等待死锁?
Posted
技术标签:
【中文标题】如何监控 MVC4 中的异步/等待死锁?【英文标题】:How to monitor for async/await deadlocks in MVC4? 【发布时间】:2013-03-22 16:44:10 【问题描述】:看完Best Practices in Asynchronous Programming 我决定测试 MVC4 中的死锁行为。从 Intranet 模板创建网站后,我修改了 Index 操作,如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
namespace AsyncAwait.MVC4.Controllers
public class HomeController : Controller
private static async Task DelayAsync()
await Task.Delay(1000);
// This method causes a deadlock when called in a GUI or ASP.NET context.
public static void Test()
// Start the delay.
var delayTask = DelayAsync();
// Wait for the delay to complete.
delayTask.Wait();
public ActionResult Index()
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
Test();
return View();
对 Index 的调用按我的预期挂起,但我也希望在某个时候抛出异常。但是,永远不会抛出异常,所有请求都会挂起。
我查看了所有可用的性能计数器,但不知道如何识别死锁。如果我要与使用 async/await 的现有网站合作,我如何设置监控潜在死锁?
谢谢!
【问题讨论】:
为什么会期望死锁会引发异常? @svick:你是对的,我不应该期待一个例外,误读了我引用的文章。我仍然想知道是否有可能以某种方式监控死锁。谢谢! 好问题。我认为这更多地与多线程有关,而不是直接与 async/await 设施有关。我认为您唯一的选择是构建某种形式的监控。我不知道使用 C# 或运行时的自动行为。 我认为在这种特定情况下,解决方案不是试图检测死锁,而是通过不使用Wait()
来完全避免它们。
@AlexS:Svick 是最好的解决方案。 (当前)在运行时没有足够的跟踪来立即检测死锁;幸运的是,像这样的死锁可靠地发生,所以很明显,一旦您进行系统级测试,就会出现死锁。随着调试和可视化工具与async
配合得更好,跟踪情况可能会在未来几年内得到改善。特别关注ETW; TPL provider 已经有一些(未记录的)事件。
【参考方案1】:
如果您希望您的任务在可预测的时间范围内完成,那么您可以使用超时。
Task.Wait
有几个采用超时值的重载。
例如,如果您的任务不应该超过 5 秒,您可以这样做。
var delayTask = DelayAsync();
// Will be true if DelayAsync() completes within 5 seconds, otherwise false.
bool callCompleted = delayTask.Wait(TimeSpan.FromSeconds(5));
if (!callCompleted)
throw new TimeoutException("Task not completed within expected time.");
【讨论】:
谢谢!这绝对是采取的方法之一。但是,我想看看是否可以在修复任何代码之前观察现有应用程序中的死锁。以上是关于如何监控 MVC4 中的异步/等待死锁?的主要内容,如果未能解决你的问题,请参考以下文章
如何修复异步 WMI 选择/PerformanceCounter 上的 UI 死锁以获取远程计算机 LastBootUpTime