提问者:小点点

为什么在我的任务中添加。wait()有时会允许任务使用主线程?


我试图理解异步是如何工作的,但有一种情况我已经简化到了极致,我找不到任何解释。

在项目上mvc ASP.NET framework 4.6:

...
public class Test {
    public static void Work(int id) {

        if (id == Thread.CurrentThread.ManagedThreadId) {
            Debug.WriteLine("******************************");
            Debug.WriteLine("***     BOOOMMMM !!!!!!!   ***");
            Debug.WriteLine("******************************");
        }
    }
}

public class HomeController : Controller {
    public ActionResult Index() {
        var id = Thread.CurrentThread.ManagedThreadId;
        Task.Run(() => { Test.Work(id); });

        return View();
    }
...

当我执行上面的代码时:

if (id == Thread.CurrentThread.ManagedThreadId)

从未验证过。DoWork()运行在另一个线程上,而不是我的主线程上。对我来说,这是正常的,这是我在阅读过程中一直明白的。

但如果我在任务上放一个等待。快跑

Task.Run(() => { Test.Work(id); }).Wait();

有时它是另一个线程而不是主要的,有时它不是,我不明白。

这里写着:

运行在线程池上启动一个任务来进行计算。ASP.NET线程池必须处理在此请求期间(意外地)丢失其线程之一的情况。

好吧,在他的例子中没有Wait(),但是这有什么区别呢,Wait()是在Work()之后调用的,所以不管有没有Wait(),Work()都应该具有相同的行为。

如果有人能给我一个解释,我将非常感激。


共1个答案

匿名用户

当您等待时,TPL可以将任务内联到当前线程中。如果任务尚未在另一个线程上启动,则可能发生这种情况。它是一种性能优化。

它是一个非常有争议的特性,将微妙的bug注入到应用程序中。本质上,任务上的任何等待都可以不确定地运行任意代码。