簡體   English   中英

等待Task.Run(...)對於控制台和Windows應用程序的行為有所不同

[英]await Task.Run(…) behaving differently for console and windows application

我有一個帶有以下代碼的控制台應用程序

static void Main(string[] args) {
    Method();
    Console.ReadKey();
}

private static void Method() {
    Task t = DoSomething();
    t.Wait();
    Console.WriteLine("Finished");
}

private static async Task DoSomething() {
    await Task.Run(() =>
        Thread.Sleep(1000));
}

一切都按我的預期工作,並且運行該程序一秒鍾后控制台顯示“ Finished”。 當我將相同的代碼移到Windows應用程序中時,我發現該程序只是停止了

private void button1_Click(object sender, EventArgs e) {
    Task t = DoSomething();
    t.Wait();
    MessageBox.Show("Finished");
}

private static async Task DoSomething() {
    await Task.Run(() =>
        Thread.Sleep(1000));
}

調試器顯示當前執行行是t.Wait(),即使已運行DoSomething方法中的Task。

在Windows應用程序中我有什么需要做的,而在控制台應用程序中我不需要做的嗎? 還是我從根本上誤會了什么?

這是經常發生的事情。 您正在造成僵局。

簡而言之,諸如WinForms和WPF之類的框架“強制”了線程同步上下文,這意味着每當啟動新任務時,其余代碼將在啟動時在同一線程上繼續。 這樣做是為了確保,例如,在任務返回后,在UI線程上啟動的代碼將繼續在同一線程上運行。

因為您正在阻塞任務(使用Wait方法),並且任務試圖將值返回到該阻塞線程,所以兩個線程都進入死鎖狀態。

在控制台應用程序中不會發生此行為,因為沒有強制執行線程同步上下文,因此任務的延續可以在完全不同的第三個線程上運行。

Stephen Cleary在這里對此進行了很好的解釋: http : //blog.stephencleary.com/2012/07/dont-block-on-async-code.html

暫無
暫無

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

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