【问题标题】:Why does adding .Wait() to my Task sometimes allow the Task to use the main thread?为什么将 .Wait() 添加到我的 Task 有时会允许 Task 使用主线程?
【发布时间】:2019-02-14 22:36:08
【问题描述】:

我试图了解异步是如何工作的,但有一种情况我已最大限度地简化了,但我找不到任何解释。

关于一个项目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 上放置一个等待

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

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

Here是这样写的:

Task.Run 在线程池上启动一个任务来进行计算。这 ASP.NET 线程池必须处理(意外地)丢失它的一个 此请求期间的线程数。

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

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

【问题讨论】:

  • 任务在调度程序上运行。当您等待或等待时,可能会选择调用线程来执行其他工作。就像它正在等待的任务一样。
  • 任务不是线程,但它们可能在另一个线程上运行。
  • 但这不是现实世界的问题。当您在另一个线程上运行任务时,您不应该关心在哪个线程上。您有时会关心调用者将继续执行的线程。
  • async 在 C# 中不是线程的同义词,而是创建一个可由任何线程完成的事件堆栈
  • Task.Wait 中记录的:“如果当前任务尚未开始执行,Wait 方法会尝试从调度程序中删除任务并在当前线程”

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


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多