async within a LINQ code - Clarification?
I don't understand why now async inside a LINQ statement - does work . Didn't we just say "don't think about using async within LINQ" ?
async
mostly doesn't work with LINQ because IEnumerable<T>
extensions don't always infer the delegate type properly and defer to Action<T>
. They have no special understanding of the Task
class. This means the actual async delegate becomes async void
, which is bad. In the case of Enumerable.Select
, we have an overload which returns a Func<T>
(which in turn will be Func<Task>
in our case), which is equivalent to async Task
, hence it works fine for async use-cases.
When the control reaches the await t here — What is actually happen? Does the control leaves the ProcessTasksAsync method ?
No, it doesn't. Enumerable.Select
is about projecting all elements in the sequence. This means that for each element in the collection, await t
which will yield control back to the iterator, which will continue iterating all elements. That's why you later have to await Task.WhenAll
, to ensure all elements have finished execution.
Question 1:
The difference is that each task is continued with additional processing which is: Trace.WriteLine(result);
. In the link you pointed to, that code does not change anything, just creates overhead of awaiting and wrapping with another task.
Question 2:
When the control reaches the await t here — What is actually happen?
It awaits for the result of ProcessTasksAsync
's task, then continue with Trace.WriteLine(result);
. We can say that the control leaves the ProcessTasksAsync
method when we have the result and the processing is still inside the anonymous method.
At the end, we have await Task.WhenAll(processingTasks);
which will await for all tasks including the additional processing (Trace.WriteLine(result);
) to complete before continuing but each task does not await for the others to continue executing: Trace.WriteLine(result);