1

I used How to: Extend the async Walkthrough by Using Task.WhenAll (C#) to develop a program to independently submit multiple database queries asynchronously. The program works ok, but there is a nuance I don't understand and for which I can't find an explanation:

In the example, the signature for the method SumPageSizesAsync is:

private async Task SumPageSizesAsync()

The body of the method SumPageSizesAsync does not explicitly return the whenAllTask object (i.e., the WhenAll roll-up Task). Why doesn't the method SumPageSizesAsync explicitly return the whenAllTask task? How does the line of code in StartButton_Click that calls SumPageSizesAsync "know" which task is being returned?

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?
}
VA systems engineer
  • 2,856
  • 2
  • 14
  • 38
  • A method marked as async wraps in a Task object whatever it is that you return from it. The accepted answer to this question explains it well: https://stackoverflow.com/questions/25191512/async-await-return-task – JonyVol Mar 25 '18 at 13:04
  • Thank-you, and I don't mean to be argumentative, but this doesn't exactly answer my question. I understand the `wrapped in a Task` part, but how does the compiler know that the `whenAllTask` task is the task that is to be returned in the absence of an explicitly coded assignment? What if the `SumPageSizesAsync` method had two or more `Task.WhenAll` statements? (assuming this is possible). – VA systems engineer Mar 25 '18 at 13:19
  • 1
    You are misunderstanding how this works. The `whenAllTask` task is **not** the task to be returned. The rest of the method is turned into a Task by the compiler and that is the Task to be returned. – Dennis_E Mar 25 '18 at 13:28
  • 1
    @Dennis_E: "Rest of the method is returned as the task": Oh, man, yes, of course. Please post this as the answer. – VA systems engineer Mar 25 '18 at 13:32
  • Read [Async Return Types](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/async-return-types). – YuvShap Mar 25 '18 at 13:51

3 Answers3

2

Why doesn't the method SumPageSizesAsync explicitly return the whenAllTask task?

That is not the Task that this method returns. The Task that is returned is one that is created by the compiler.
As soon as the await is encountered, the following happens:
- If whenAllTask is already finished, then just continue executing the rest of the method.
- Otherwise, create a Task that does the following things:
1: Wait for whenAllTask to finish.
2: and then execute the rest of the method.
This Task is then immediately returned.
I always think of the return statement as being embedded in the await. "return a Task that waits for this other Task to finish and then executes the rest of this method."

Dennis_E
  • 8,751
  • 23
  • 29
0

I completely agree on answer posted by @Dennis_E and more information can also be found in C# 6 in a Nutshell (page number 600).

According to author, while executing the async function, with task return type. If there is no explicit return of task from the method body, complier creates a task.

This task is then used for following purpose,

  1. Singling completion of the method.
  2. Asynchronous call chaining.
RJ-
  • 136
  • 1
  • 13
-1

It is an async void function, meaning it returns Task. Since it is already awaited inside, there is nothing no return here.

Daniel Stoyanoff
  • 1,443
  • 1
  • 9
  • 25
  • 1
    This "It is an async void function, meaning it returns Task" makes no sense. Either it's `void` or it `returns`, you cannot have both – Camilo Terevinto Mar 25 '18 at 13:16
  • Just to be precise: An `async void` method would have a signature: `async void MyFunc()`. My method's signature is `async Task SumPageSizesAsync()` and so returns a Task (as Dennis_E taught me, the task is the code in `SumPageSizesAsync` between the await and the end of the `SumPageSizesAsync()` (exclusive of the await). A valid/expected/meaningful use of an `async void` method is the event handler (a button click event) that invokes the process. Otherwise, an `async void` method is a method whose result cannot be tracked since a Task or a Task is not returned,i.e., kind of useless. – VA systems engineer Mar 25 '18 at 14:58