簡體   English   中英

異步等待:主線程是否掛起?

[英]async await: is the main thread suspended?

我正在閱讀有關async/await關鍵字的內容,並且已閱讀:

當邏輯流到達 await 標記時,調用線程將掛起,直到調用完成。

好吧,我創建了一個簡單的windows forms application ,放置了兩個標簽、一個按鈕和一個文本框,然后我編寫了代碼:

        private async void button1_Click(object sender, EventArgs e)
        {
            label1.Text = Thread.CurrentThread.ThreadState.ToString();
            button1.Text =  await DoWork();
            label2.Text = Thread.CurrentThread.ThreadState.ToString();
        }

        private Task<string> DoWork()
        {
            return Task.Run(() => {
                Thread.Sleep(10000);
                return "done with work";
            });            
        }

我不明白的是,當我單擊按鈕時,label1 將顯示正在Running的文本,並且標簽將在 10 秒后顯示相同的文本,但是在這 10 秒內,我能夠在我的文本框中輸入文本,所以看起來主線程正在運行......

那么,async/await 是如何工作的呢?

這是書中的“截圖”: 在此處輸入圖片說明

問候

我讀過:當邏輯流到達等待標記時,調用線程將掛起,直到調用完成。

你從哪里讀到的那些廢話? 要么有一些您沒有引用的上下文,要么您應該停止閱讀包含此內容的任何文本。 await 的目的是做相反的事情。 await 的目的是讓當前線程在異步任務進行中時做有用的工作

更新:我下載了你引用的書。 該部分中的所有內容絕對都是錯誤的。 扔掉這本書,買一本更好的書。

我不明白的是,當我單擊按鈕時,標簽 1 將顯示正在運行的文本,標簽將在 10 秒后顯示相同的文本,但在這 10 秒內,我能夠在文本框中輸入文本,所以看起來主線程正在運行......

沒錯。 這是發生的事情:

        label1.Text = Thread.CurrentThread.ThreadState.ToString();

文本已設置。

        button1.Text =  await DoWork();

一堆事情在這里發生。 首先會發生什么? DoWork被調用。 它有什么作用?

        return Task.Run(() => { Thread.Sleep(10000);

它從線程池中取出一個線程,讓該線程休眠 10 秒,然后返回一個代表該線程正在完成的“工作”的任務。

現在我們回到這里:

        button1.Text =  await DoWork();

我們手頭有任務。 Await 首先檢查任務是否已經完成。 不是。 接下來,它將此方法的其余部分注冊為任務的繼續 然后它返回給它的調用者。

嘿,它的調用者是什么? 反正我們是怎么到這里的?

一些代碼調用了這個事件處理程序; 它是處理 Windows 消息的事件循環。 它看到一個按鈕被點擊並分派給剛剛返回的點擊處理程序。

現在會發生什么? 事件循環繼續運行。 正如您所注意到的,您的 UI 一直運行良好。 最終該線程會滴答十秒,任務的繼續被激活。 那有什么作用?

這會在 Windows 隊列中發布一條消息,說“您現在需要運行該事件處理程序的其余部分;我得到了您正在尋找的結果。”

主線程事件循環最終會得到該消息。 所以事件處理程序從它停止的地方開始:

        button1.Text =  await DoWork();

await 現在從任務中提取結果,將其存儲在按鈕文本中,然后返回到事件循環。

async / await創建一個狀態機,為您處理延續。 一個非常粗略的等價物(沒有一堆特征)是一個顯式的延續方法,例如:

private void button1_Click_Continuation(string value)
{
    button1.Text = value;
    label2.Text = Thread.CurrentThread.ThreadState.ToString();
}

private void button1_Click(object sender, EventArgs e)
{
    label1.Text = Thread.CurrentThread.ThreadState.ToString();
    DoWork(button1_Click_Continuation);
}

private void DoWork(Action<string> continuation)
{
    Task.Run(() => {
        Thread.Sleep(10000);
        continuation("done with work");
    });
}

請注意,我仍在使用Task.Run在單獨的線程上運行。 注意這個版本是沒​​有進度跟蹤的(原來可以把button1_Click的返回值改成Task看是否完成)。

除了上述轉換之外,系統還智能判斷Task是否在 UI 線程上啟動並再次編組回 UI 線程以確保一切按預期進行。 這可能是您沒有意識到的主要事情,但在狀態機方面的擴展有時會解釋asyc / await真正含義(而不是讓它變得神秘)。

通過編寫await ,您是在說 - 此時請停止執行該方法,等待DoWork完成,然后再繼續。

與異步並等待(C#),異步編程在異步方法部分會發生什么有一個一步一步的解釋,與圖片的在發生什么, async方法。

更好的解釋是await (C# 參考) 看看下面對WaitSynchronouslyWaitAsynchronouslyAsync評論。

該文章還指出(強調我的):

await 運算符應用於異步方法中的任務,以暫停該方法的執行直到等待的任務完成。 任務代表正在進行的工作。

private async void button1_Click(object sender, EventArgs e)
{
    // Call the method that runs asynchronously.
    string result = await WaitAsynchronouslyAsync();

    // Call the method that runs synchronously.
    //string result = await WaitSynchronously ();

    // Display the result.
    textBox1.Text += result;
}

// The following method runs asynchronously. The UI thread is not
// blocked during the delay. You can move or resize the Form1 window 
// while Task.Delay is running.
public async Task<string> WaitAsynchronouslyAsync()
{
    await Task.Delay(10000);
    return "Finished";
}

// The following method runs synchronously, despite the use of async.
// You cannot move or resize the Form1 window while Thread.Sleep
// is running because the UI thread is blocked.
public async Task<string> WaitSynchronously()
{
    // Add a using directive for System.Threading.
    Thread.Sleep(10000);
    return "Finished";
}

基本上,關鍵是程序執行以同步方式繼續,直到或除非遇到 await。 一旦遇到 await,假設對於任務 A,編譯器將切換回調用此異步方法的 main 方法,而無需使用 await 關鍵字,並將繼續從任務 A 的調用點執行程序,因為編譯器知道它必須等待完成任務 A 那么為什么不完成它的其他待處理任務。

這里發生的事情是 main 方法中不等待 button1_Click 事件,因此一旦遇到 await DoWork() 它將繼續執行。 DoWork() 完成后,編譯器將繼續執行 button1_Click 中的進一步代碼

暫無
暫無

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

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