TaskXAsync() { await XXAsync(); await XXXAsync(); }
上面已清楚,这两个仅仅按顺序执行,并不能并行执行,势必影响执行效率,那么如何才能让他们并行执行呢? microsoft有专门的方法 Task.WhenAll(Tasks) 我们可以看看microsoft的例子 如:
await SumPageSizesAsync();
private async Task SumPageSizesAsync() { // Make a list of web addresses. List<string> urlList = SetUpURLList(); // Declare an HttpClient object and increase the buffer size. The // default buffer size is 65,536. HttpClient client = new HttpClient() { MaxResponseContentBufferSize = 1000000 }; // Create a query. IEnumerable<Task<int>> downloadTasksQuery = from url in urlList select ProcessURL(url, client); // Use ToArray to execute the query and start the download tasks. Task<int>[] downloadTasks = downloadTasksQuery.ToArray(); // You can do other work here before awaiting. [] lengths = await Task.WhenAll(downloadTasks); Task<int[]> whenAllTask = Task.WhenAll(downloadTasks); total = lengths.Sum(); //var total = 0; //foreach (var url in urlList) //{ // // GetByteArrayAsync returns a Task<T>. At completion, the task // // produces a byte array. // byte[] urlContent = await client.GetByteArrayAsync(url); // // The previous line abbreviates the following two assignment // // statements. // Task<byte[]> getContentTask = client.GetByteArrayAsync(url); // byte[] urlContent = await getContentTask; // DisplayResults(url, urlContent); // // Update the total. // total += urlContent.Length; //} // Display the total count for all of the web addresses. resultsTextBox.Text += , total); }
Task<int> ProcessURL(string url, HttpClient client) { byte[] byteArray = await client.GetByteArrayAsync(url); DisplayResults(url, byteArray); return byteArray.Length; }
private List<string> SetUpURLList() { List<string> urls = new List<string> { , , , , , , , , }; return urls; }
上面的例子很简单了,组合任务Tasks,传给 await Task.WhenAll(Tasks) 这样,多个await 就并行得到了执行。
从上面的例子,我们看得出,每个嵌套的方法里,都是层层向上await,这就是await链,不仅要作标记在子线程完成时,在此处”唤醒“同时达到快速响应调用线程,逐层向上返回,结果只有一个,最终让最外层的调用者及时响应,而不用等待,就像MVC原理一样,提高“吞吐量”。
但是中间有一个方法,没向上await,被调用者依然是按照执行的方式决定是同步还是异步。被调者,要是有返回值的,调用者,是没办法获取到返回值的,因为,我们并没办法知道,此方法是否已完成,所以,可能在以后的某段代码中依然要用await 调用。
小结:await与async并不能决定方法是同步还是异步,而真正执行异步的还是靠Task、异步委托或其它方式,await的主要作用是,
挂机耗时异步方法,把控制权及时的交给调用者,并在被调用者完成任务时,能够在此唤醒,并继续执行其它方法。
本节的内容,部分例子只起到说明作用,来原于实践的验证,由于时间仓促,并没有提供完整的案例。
同时本节内容主要用简单的语言来加以说明,希望能给读者阐明原理,如果读者希望更清楚的知道await和async,可以查看源代码
如果对于异步的更多了解请参考:
大话异步与并行(一) 大话异步与并行(二) 大话异步与并行(三)
本文部分实例参考
await(C# 参考) https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/await使用 Async 和 Await 的异步编程 (C#) https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/index
Task.WhenAll 方法 (IEnumerable<Task>) https://msdn.microsoft.com/zh-cn/library/windows/apps/hh160384(v=vs.110)
作者:谷歌's(谷歌's博客园)
出处: 欢迎转载,但任何转载必须保留完整文章,在显要地方显示署名以及原文链接。如您有任何疑问或者授权方面的协商,请给我留言。