考虑以下(基于默认的 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;
inasync
只会在路由已经完成之后发生- 基本上,系统似乎不愿意使用任何线程来恢复async
操作,直到请求完成之后。更糟糕的是:如果我们使用过.Wait()
(或访问过.Result
),那么它将完全死锁。
那么:那是怎么回事?明显的解决方法是“不涉及”,但这在使用库等时并不容易。最终,和之间async
没有功能差异(尽管存在明显的结构差异)。SlowDouble
IndirectSlowDouble
注意:控制台/winform/等中完全相同的东西可以正常工作。