我試圖弄清楚如何在 C# 中啟動異步主方法。為此,我想創建一個與異步主執行緒相同的新執行緒示例。
這是在沒有異步的情況下完成的:
class Program
{
public static void Main(string[] args)
{
Thread t = new Thread(Main2)
{ IsBackground = false };
t.Start();
}
public static void Main2()
{
Console.WriteLine("Helloooo");
Thread.Sleep(1000);
Console.WriteLine("Woooorld");
}
}
如果我運行上面的代碼,將列印以下內容:
Helloooo
Woooorld
您可以看到我沒有添加 at.Join()那是因為 t 是前臺執行緒。但是,如果嘗試對 async 執行相同操作,則會發生以下情況:
class Program
{
public static void Main(string[] args)
{
Thread t = new Thread(Main2)
{ IsBackground = false };
t.Start();
}
// Can't use "public static async Task main2"
// because you need to pass in a void method to a new thread
public static async void Main2()
{
Console.WriteLine("Helloooo");
await Task.Delay(1000);
Console.WriteLine("Woooorld");
}
}
僅有的
Helloooo
列印出來,程式退出,即使新執行緒是前臺執行緒。現在我明白了這里發生了什么,當新執行緒到達await Task.Delay(1000);時它啟動一個狀態機并釋放執行緒用于其他事情。我想知道的是我必須改變什么才能讓我原來的執行緒死掉,讓我的新執行緒接管。我想了解異步/等待鏈是如何啟動的。
uj5u.com熱心網友回復:
一篇關于 C# 7.1 的文章說:
“通過允許入口點回傳任務/任務并標記為異步,允許在應用程式的主/入口點方法中使用等待。”
public static void Main()
{
MainAsync().GetAwaiter().GetResult();
}
private static async Task MainAsync()
{
... // Main body here
}
“我們可以消除對這個樣板的需求,并且只需允許 Main 本身是異步的,這樣就可以在其中使用 await,從而更容易開始。”
來源:https ://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-7.1/async-main
如您所見,它們不會啟動單獨的執行緒,而是“阻塞”當前執行緒,直到 MainAsync 回傳任務 IsCompleted。
uj5u.com熱心網友回復:
發生這種情況是由于以下因素的組合:
- 在控制臺應用程式中,
SynchronizationContext.Current未設定。 - 如果
SynchronizationContext.Current未設定,則在 ThreadPool 執行緒上呼叫等待回應(例如,在您的示例中列印“Woooorld”)。 - ThreadPool 執行緒是后臺執行緒。
uj5u.com熱心網友回復:
async Task Main()由編譯器重寫,如下所示:
static void Main() {
YourAsyncMain().GetAwaiter().GetResult();
}
static async Task YourAsyncMain() {
Console.WriteLine("Test");
Console.ReadKey();
}
不需要額外的執行緒,你已經有主執行緒來執行你的異步主函式并阻塞直到它完成。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/520365.html
標籤:C#多线程异步异步等待
