gpt4 book ai didi

c# - Task.WaitAll 一直在循环

转载 作者:行者123 更新时间:2023-11-30 19:28:49 28 4
gpt4 key购买 nike

我正在尝试使用此异步代码来测试异步关键字:

public async Task<string> AsyncMethod()
{
var link = "http://www.google.com";

var webclient = new WebClient();
var result = await webclient.DownloadStringTaskAsync(new Uri(link));

return result;
}

public async Task<ActionResult> Index()
{
var a = AsyncMethod();
var b = AsyncMethod();

Task.WaitAll(a, b);

return View();
}

但是当我调试它时,调试器会触发 Task.WaitAll 并且什么都不做(返回键永远不会执行)..如果我在两个“AsyncMethod”之前设置 await 并删除 Task.WaitAll 它会起作用。那么我做错了什么?

最佳答案

因为您的方法看起来像 ASP.NET MVC Controller 操作,所以我假设您正在 ASP.NET 上运行。

默认情况下,异步方法会在它暂停的同一上下文中恢复(即您调用 await 的地方)。在 ASP.NET 中,这意味着当前请求上下文。并且一次只能有一个线程处于特定上下文中。因此,发生的情况是执行 Index() 的线程在请求​​上下文中,被阻塞在 WaitAll() 中。另一方面,AsyncMethod() 的两次调用都试图在同一上下文中恢复(在完成下载后),但它们无法这样做,因为 Index() 仍在该上下文中执行。因此,这些方法位于 deadlock 中。所以什么也没有发生。

(同样的死锁也会发生在 GUI 应用程序中,因为 GUI 上下文在这方面的行为相似。控制台应用程序没有这个问题,因为它们没有任何上下文。)

解决这个问题有两个方面:

  1. 永远不要同步等待 async 方法。 (可能唯一的异常(exception)是如果想从控制台应用程序的 Main() 方法执行异步方法。)

    相反,异步等待它们。在您的情况下,这意味着使用 await Task.WhenAll(a, b)

  2. 在您的“库”方法中使用 ConfigureAwait(false)(即那些实际上不需要在请求上下文中执行的方法)。

使用 1 或 2 可以解决您的问题,但最好同时进行。

有关此问题的更多信息,请阅读 Stephen Cleary 的文章 Don't Block on Async Code .

关于c# - Task.WaitAll 一直在循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14046471/

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