C# Async和await:为什么签名定义任务返回类型的异步方法不显式返回任务?

C# Async和await:为什么签名定义任务返回类型的异步方法不显式返回任务?,c#,async-await,task,C#,Async Await,Task,我曾经开发过一个程序,可以独立地异步提交多个数据库查询。程序运行正常,但有一个细微差别我不理解,也找不到解释: 在本例中,方法SumPageSizesAsync的签名为: 专用异步任务SumPageSizesAsync 方法SumPageSizesAsync的主体不显式返回whenAllTask对象,即WhenAll汇总任务。为什么SumPageSizesAsync方法不显式返回whenAllTask任务?StartButton_Click中调用SumPageSizesAsync的代码行如何知道

我曾经开发过一个程序,可以独立地异步提交多个数据库查询。程序运行正常,但有一个细微差别我不理解,也找不到解释:

在本例中,方法SumPageSizesAsync的签名为:

专用异步任务SumPageSizesAsync

方法SumPageSizesAsync的主体不显式返回whenAllTask对象,即WhenAll汇总任务。为什么SumPageSizesAsync方法不显式返回whenAllTask任务?StartButton_Click中调用SumPageSizesAsync的代码行如何知道返回了哪个任务

private async void StartButton_Click(object sender, RoutedEventArgs e)
{
    .
    Task sumTask = SumPageSizesAsync();
    .
}


private async Task SumPageSizesAsync()
{
    HttpClient client = new HttpClient() { MaxResponseContentBufferSize = 1000000 };

    List<string> urlList = SetUpURLList();

    IEnumerable<Task<int>> downloadTasksQuery = from url in urlList select ProcessURLAsync(url);
    Task<int>[] downloadTasks = downloadTasksQuery.ToArray();

    Task<int[]> whenAllTask = Task.WhenAll(downloadTasks);

    int[] lengths = await whenAllTask;

    int total = lengths.Sum();

    // Display the total count for all of the web addresses.  
    resultsTextBox.Text += string.Format("\r\n\r\nTotal bytes returned:  {0}\r\n", total);

    // where's the return statement?
}

它是一个异步void函数,意味着它返回任务。因为它已经在里面等待了,所以这里没有任何回报

为什么SumPageSizesAsync方法不显式返回whenAllTask任务

这不是此方法返回的任务。返回的任务是由编译器创建的任务。 一旦遇到等待,就会发生以下情况: -如果whenAllTask已经完成,那么只需继续执行该方法的其余部分。 -否则,请创建执行以下操作的任务: 1:等待Whenall任务完成。 2:然后执行方法的其余部分。 然后立即返回此任务。
我总是认为return语句嵌入在wait语句中。返回一个等待另一个任务完成的任务,然后执行此方法的其余部分。

我完全同意@Dennis_E给出的答案,更多信息也可以在C 6中的600页中找到

据作者介绍,在执行异步函数时,使用任务返回类型。如果没有从方法体显式返回任务,编译器将创建一个任务

然后将此任务用于以下目的:

方法的单点完成。 异步调用链。
标记为async的方法在任务对象中包装,无论从中返回的是什么。这个问题的公认答案很好地解释了这一点:谢谢,我并不想争论,但这并不能完全回答我的问题。我理解包装在任务部分中的任务,但是编译器如何知道whenAllTask任务是在没有显式编码赋值的情况下返回的任务?如果SumPageSizesAsync方法有两个或多个Task.Wheall语句,该怎么办?假设这是可能的。你误解了它的工作原理。whenAllTask任务不是要返回的任务。方法的其余部分由编译器转换为任务,这就是要返回的任务。@Dennis_E:方法的其余部分作为任务返回:哦,伙计,是的,当然。请将此作为答案发布。请阅读。这是一个异步void函数,意味着它返回的任务毫无意义。无论它是void还是返回,都不能两者兼而有之,必须精确:异步void方法将有一个签名:async void MyFunc。我的方法的签名是async Task SumPageSizesAsync,因此返回一个任务,正如Dennis_E教我的那样,该任务是SumPageSizesAsync中等待和SumPageSizesAsync结束之间的代码,不包括等待。async void方法的有效/预期/有意义的使用是事件处理程序调用流程的按钮单击事件。否则,异步void方法是一种无法跟踪其结果的方法,因为没有返回任务或任务,即某种无用的方法。