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

时间:2018-09-10 13:17:37

标签: c# task task-parallel-library threadpool

我试图了解异步的工作原理,但有一种情况我已将其简化到最大程度,并且找不到任何解释。

在项目mvc asp.net框架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

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

有时候是主线程之外的另一个线程,有时不是,我不理解。

Here如下:

  

Task.Run在线程池上启动一个任务以进行计算。的   ASP.NET线程池必须处理(意外地)丢失其线程之一   在此请求的持续时间内保持线程状态。

好的,在他的示例中没有Wait(),但是有什么区别,无论如何,在Work()之后调用Wait(),因此无论是否有Wait(),Work()都应始终具有相同的行为

如果有人可以给我一个解释,我将不胜感激。

1 个答案:

答案 0 :(得分:1)

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

It is a very controversial feature that injects subtle bugs into applications.本质上,对任务的任何等待都可以不确定地运行任意代码。