如果你正在寫一個控制臺程序,你可能最終想要一個異步的main方法,像這樣:
class PRogram{ static async void Main(string[] args) { ... }}
很不幸,那個沒用(實際上,VS 11 編譯器拒絕異步Main方法)。我的這篇博客《Async and Await 異步和等待》里講過,當異步方法完成后會返回到它的調用者。雖然這在UI應用(方法僅僅返回到UI事件循環)和asp.net(方法脫離線程返回但請求還是活著的【在生命周期內】)中運行很完美,但在控制臺程序中不會工作得這么好:因為Main返回到操作系統,因此你的程序退出了。
你可以通過提供你自己的兼容異步上下文來變通一下。AsyncContext(異步上下文)是通用的上下文,它用來啟用異步的MainAsync:
class Program{ static int Main(string[] args) { try { return AsyncContext.Run(() => MainAsync(args)); } catch (Exception ex) { Console.Error.WriteLine(ex); return -1; } } static async Task<int> MainAsync(string[] args) { ... }}
以下為一個較為常見的問題,望園友們注意!
問:關于使用".Wait()"來等待一個來自非異步的Main方法的異步方法,推薦使用AsyncContext嗎?
答:在Main方法中要么使用AsyncContext,要么使用GetAwaiter().GetResult()。GetAwaiter().GetResult()本質上和Wait()一樣,但是它沒有把異常封裝在AggregateException中。
AsyncContext在主控制臺線程中裝配了一個真實的單線程上下文。GetAwaiter().GetResult()將自由上下文默認保留在控制臺應用中。如果我在寫一個概念證明型的代碼,并且最終在ASP.NET或者UI應用(具有單線程上下文)中終止,我通常就會使用AsyncContext;如果我在寫一個真實的控制臺應用,我可以任選一種方式。
新聞熱點
疑難解答