簡體   English   中英

等待創建另一個線程嗎?

[英]Does await create another thread?

我閱讀了有關異步並等待的Microsoft文檔 它說:

async和await關鍵字不會導致創建其他線程。

但是我運行下面的代碼

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain
    {
        static void Main()
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            Task task = Test();
            task.Wait();
        }

        public async static Task Test()
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            await Task.Delay(1000);
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
        }

    }
}

結果是

1個
1個
4

很明顯,

await Task.Delay(1000);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

在另一個線程中運行。 為什么文檔說沒有創建線程?

我已經閱讀了上一個問題,使用async / await是否會創建一個新線程? ,但它不能回答我的問題,那里的答案只是從Microsoft來源復制粘貼。 為什么在測試中看到不同的線程ID?

我總是鼓勵人們閱讀我的async介紹 ,並跟進async最佳實踐 綜上所述:

默認情況下, await捕獲“上下文”,並在該上下文中繼續執行async方法。 在這種情況下,上下文是線程池上下文。 因此,這就是為什么您看到Test恢復在線程池線程上執行的原因。

asyncawait本身不會創建任何其他線程; 例如,如果您在UI應用程序中執行相同的操作,則“上下文”將是UI線程,而Test將繼續在該UI線程上執行。 但是由await隱式捕獲的上下文負責調度asnc連續,並且在此示例中,上下文只是將其調度到線程池。

您在測試中看到了不同的線程ID,因為使用了不同的線程來執行代碼。 這並不意味着異步/等待導致了其他線程的創建。 在這種情況下,使用的線程已經存在於稱為線程池的線程池中。

有兩個不同的想法:

  • 代表要完成的工作的任務, 以及
  • 如何實際處理任務(例如計划和執行)

Async / await與前者有關,但是您的測試代碼告訴您有關后者的信息:處理這些任務的特定機制。

該機制由上下文決定。 一些上下文使用多個線程(但是請注意,上下文取決於它如何管理這些線程,包括是否以及何時創建新線程),但某些上下文僅使用1個線程。

使用了多個線程是與上下文有關的,而不是異步/等待。

我改變了你的例子:

public async static Task Test()
{
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    await Task.CompletedTask; // <--- instead of Task.Delay()
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}

現在輸出為1、1、1。

await未創建新線程。 Task.Delay是元凶!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM