如何正确编写异步方法?
所以我想学习在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方法应该返回Task
或Task
,如果你什么都不返回,并且你希望你的方法是异步运行的,你应该像这样定义你的方法:
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();