
今天有點疑惑就寫了個測試的代碼,發現控制台和Winform中不一樣
比如:
控制台:
...Main(){ Test(); }
private static async void Test()
{
Show("Test.Before");
await Task.Run(() => { Thread.Sleep(2000); Show("Test.Task"); });
Show("Test.After");//輸出字符串和當前線程
}
private static void Show(string str)
{
Console.WriteLine($"{str}:{Thread.CurrentThread.ManagedThreadId}\r\n");
}
輸出:
Test.Before:1
Test.Task:3
Test.After:3
Winform中:
...test(){ Test(); }
private async void Test()
{
Show("Test.Before");
await Task.Run(() => { Thread.Sleep(2000); });
Show("Test.After");//輸出字符串和當前線程
}
public void Show(string str)
{
richTextBox1.AppendText($"{str}:{Thread.CurrentThread.ManagedThreadId}\r\n");
}
輸出:
Test.Before:1
Test.After:1
為什么這兩個不一樣呢?新手求解答
對於當前運行的winform程序,始終只有一個UI線程
@JoySn: 控制台程序沒有主線程,程序跟着線程跑,啟動線程3,就在一直在線程3里跑,除非再創建新的線程
@JoySn: 所以在控制台程序中同步方法中調用異步方法不會發生死鎖
因為調用 Task 的 Run 之后返回的是 Task 在等待 Task 的時候可以設置 ConfigWait() 參數,通過這個參數可以設置之后是否返回主線程。
在控制台使用的時候,因為控制台沒有 dispatcher 調度,所以在執行 Task 的run 等待就會發現當前的調度就是 Task 所在的線程,所以在控制台就是在創建 Task 的線程
在 WinForm 因為有主線程,所以從 Task 的 run 方法可以回到主線程
Show("Test.Before");
await Task.Run(() => { Thread.Sleep(2000); }).ConfigureAwait(true);
Show("Test.After");
Test.Before:1
Test.After:1
Show("Test.Before");
await Task.Run(() => { Thread.Sleep(2000); }).ConfigureAwait(false);
Show("Test.After");
Test.Before:1
Test.After:3
那在控制台中,Task.Run里不是開了一個子線程3嗎?await結束后也是3執行的。主要是疑惑為什么控制台中await結束后線程不是1,而是子線程3