Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

async within a LINQ code - Clarification?

Almost every SO's answer regarding this topic , states that :

LINQ doesn't work perfectly with async

Also :

I recommend that you not think of this as "using async within LINQ"

But in Stephen's book there is a sample for :

Problem: You have a collection of tasks to await, and you want to do some processing on each task after it completes. However, you want to do the processing for each one as soon as it completes, not waiting for any of the other tasks.

One of the recommended solutions was :

static async Task<int> DelayAndReturnAsync(int val)
{
 await Task.Delay(TimeSpan.FromSeconds(val));
 return val;
}

// This method now prints "1", "2", and "3".
static async Task ProcessTasksAsync()
{
 // Create a sequence of tasks.
 Task<int> taskA = DelayAndReturnAsync(2);
 Task<int> taskB = DelayAndReturnAsync(3);
 Task<int> taskC = DelayAndReturnAsync(1);
 var tasks = new[] { taskA, taskB, taskC };
 var processingTasks = tasks.Select(async t =>
    {
    var result = await t;
    Trace.WriteLine(result);
    }).ToArray();

// Await all processing to complete
await Task.WhenAll(processingTasks);

}

Question #1:

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" ?

Question #2:

When the control reaches the await t here — What is actually happen? Does the control leaves the ProcessTasksAsync method ? or does it leaves the anonymous method and continue the iteration ?

like image 992
Royi Namir Avatar asked Jul 18 '15 09:07

Royi Namir


People also ask

What is async LINQ?

Evolution of An Async LINQ operator LINQ (Language-Integrated Query) has been around for quite a while in the world of.NET (since.NET Framework 3.5 and C# 3.0) but recently async streams (i.e. IAsyncEnumerable<T>) were added to.NET and with them came async LINQ.

What is LINQ query syntax?

Query syntax is similar to SQL (Structured Query Language) for the database. It is defined within the C# or VB code. The LINQ query syntax starts with from keyword and ends with select keyword. The following is a sample LINQ query that returns a collection of strings which contains a word "Tutorials".

When a method is async the naming convention suggest to?

When a method is async the naming convention suggest that you append "Async" to your method name. By convention, you append "Async" to the names of methods that have an Async or async modifier.

Why is my LINQ query so long?

A LINQ query is often a little longer horizontally than your usual code. When you now try to give every lambda variable a good name, your line will certainly get way longer, you might use your variable repeatedly, and you might find it harder to break your code.


1 Answers

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.

like image 88
Yuval Itzchakov Avatar answered Sep 26 '22 20:09

Yuval Itzchakov