Task.WaitAll保持循环 [英] Task.WaitAll keeps in loop

查看:120
本文介绍了Task.WaitAll保持循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试此异步代码,仅用于测试async关键字:

I'm trying this async code just for testing the async keyword:

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则它起作用..那么我在做什么错了?

but when I debug it, the debugger hits the Task.WaitAll and just do nothing(the return keywork is never executed).. If I set await before the two 'AsyncMethod' and remove the Task.WaitAll it works.. So what am I doing wrong?

推荐答案

由于您的方法看起来像ASP.NET MVC控制器操作,因此我假设您正在ASP.NET上运行.

Because your method looks like ASP.NET MVC controller action, I'm assuming you're running on ASP.NET.

默认情况下,异步方法在被暂停的同一上下文(即您调用await的位置)上恢复.在ASP.NET中,这表示当前请求上下文.一次只能在一个特定的上下文中使用一个线程.因此,发生的事情是执行Index()的线程在请求​​上下文中,并在WaitAll()中被阻塞.另一方面,AsyncMethod()的两个调用都试图在相同的上下文(完成下载后)上恢复,但是他们不能这样做,因为Index()仍在该上下文中执行.因此,这些方法位于死锁中,因此没有任何反应.

By default, an async method resumes on the same context where it was suspended (i.e. where you called await). In ASP.NET, this means the current request context. And only one thread can be in a specific context at a time. So, what happens is that the thread that executes Index() is in the request context, blocked in WaitAll(). On the other hand, both invocations of AsyncMethod() are trying to resume on the same context (after they finished downloading), but they are unable to do so, because Index() is still executing in that context. Because of this, the methods are in a deadlock and so nothing happens.

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

(The same deadlock would also happen in an GUI application, because GUI context behave similarly in this regard. Console applications don't have this issue, because they don't have any context.)

此问题的解决方法是双重的:

The fix for this is twofold:

  1. 请不要同步等待async方法. (可能唯一的例外是如果要从控制台应用程序的Main()方法执行异步方法.)

  1. Never wait synchronously for an async method. (Probably the sole exception is if want to execute an async method from the Main() method of a console application.)

相反,异步等待它们.就您而言,这意味着使用await Task.WhenAll(a, b).

Instead, wait for them asynchronously. In your case, that means using await Task.WhenAll(a, b).

在您的库"中使用ConfigureAwait(false)方法(即不需要强制执行的方法).

Use ConfigureAwait(false) in your "library" methods (i.e. those that don't actully need to execute on the request context).

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

Using 1 or 2 would fix your issue, but it's probably best if you do both.

有关此问题的更多信息,请阅读Stephen Cleary的文章

For some more information about this issue, read Stephen Cleary's article Don't Block on Async Code.

这篇关于Task.WaitAll保持循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆