如何正确编写异步方法?

所以我想学习在C#中使用’async’和’await’的基础知识,但我不确定我在这里做错了什么。 我期待以下输出:

Calling DoDownload DoDownload done [...output here...] 

但我没有得到下载的输出,我也期望“完成”,但这需要一段时间。 不应该立即输出吗? 此外,我似乎无法获得字符串结果。 这是我的代码:

 namespace AsyncTest { class Program { static void Main(string[] args) { Debug.WriteLine("Calling DoDownload"); DoDownloadAsync(); Debug.WriteLine("DoDownload done"); } private static async void DoDownloadAsync() { WebClient w = new WebClient(); string txt = await w.DownloadStringTaskAsync("http://www.google.com/"); Debug.WriteLine(txt); } } } 

要获得所需的行为,您需要在退出Main()之前等待该过程完成。 为了能够告诉您的进程何时完成,您需要返回一个Task而不是函数中的void ,除非您正在处理事件,否则不应该从async函数返回void

正确运行的程序的重写版本将是

 class Program { static void Main(string[] args) { Debug.WriteLine("Calling DoDownload"); var downloadTask = DoDownloadAsync(); Debug.WriteLine("DoDownload done"); downloadTask.Wait(); //Waits for the background task to complete before finishing. } private static async Task DoDownloadAsync() { WebClient w = new WebClient(); string txt = await w.DownloadStringTaskAsync("http://www.google.com/"); Debug.WriteLine(txt); } } 

因为您无法在Main() await ,所以我必须执行Wait()函数。 如果这是一个具有SynchronizationContext的应用程序,我会await downloadTask; 相反,并使该函数从async调用。

您正在调用DoDownloadAsync(),但您不等待它。 所以你的程序将进入下一行。 但是还有另一个问题,Async方法应该返回TaskTask ,如果你什么都不返回,并且你希望你的方法是异步运行的,你应该像这样定义你的方法:

 private static async Task DoDownloadAsync() { WebClient w = new WebClient(); string txt = await w.DownloadStringTaskAsync("http://www.google.com/"); Debug.WriteLine(txt); } 

并且在Main方法中,您无法等待DoDownloadAsync ,因为您不能在非异步函数中使用await关键字,并且您无法进行Main异步。 所以考虑一下:

 var result = DoDownloadAsync(); Debug.WriteLine("DoDownload done"); result.Wait();