我试图理解异步是如何工作的,但有一种情况我已经简化到了极致,我找不到任何解释。
在项目上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()都应该具有相同的行为。
如果有人能给我一个解释,我将非常感激。
当您等待时,TPL可以将任务内联到当前线程中。如果任务尚未在另一个线程上启动,则可能发生这种情况。它是一种性能优化。
它是一个非常有争议的特性,将微妙的bug注入到应用程序中。本质上,任务上的任何等待都可以不确定地运行任意代码。