Reputation: 1069
Let's consider this code :
var tasks = actionItems.Select(t => DoSmthAsync());
var resultAll = await Task.WhenAll(tasks);
And method:
public async Task<int> DoSmthAsync()
{
Debug.WriteLine("Threadid=" + Thread.CurrentThread.ManagedThreadId);
var result = await DoSmthAnotherAsync();
Debug.WriteLine("ThreadId=" + Thread.CurrentThread.ManagedThreadId);
return result;
}
I expect that this will be executed parallel in different threads, but I see that it work in the same thread. Also, I don't understand when a task run?
Upvotes: 2
Views: 1378
Reputation: 44026
I expect that this will be executed parallel in different threads.
This was explained in Victor Wilson's answer, so I'll focus on explaining only this:
Also, I don't understand when a task run?
A Task
is usually started when it is created (in which case it is called a hot task). Async methods and all built-in .NET APIs return hot tasks. It is possible to create a non-started Task
by using the Task
constructor (creating a so called cold task), but these tasks are normally started internally by the same library that created them. Exposing a cold task to the external world, end expecting the callers to Start
it, is something that I have never seen, and it would be highly surprising (in an unpleasant way) if existed.
This constructor should only be used in advanced scenarios where it is required that the creation and starting of the task is separated.
var tasks = actionItems.Select(t => DoSmthAsync());
This line of code doesn't create any tasks, so no task is started at this point. The Select
LINQ method returns a deferred enumerable sequence, not a materialized collection. The actual materialization of the tasks happens when you call the method Task.WhenAll(tasks)
.
Upvotes: 2
Reputation: 1891
You're confusing the async await
model with parallel programming.
Select
will iterate over your actionItems
serially. DoSmthAsync
will return control to the caller (the Select
iterator in this case) when you await DoSmthAnotherAsync
and so you get a list of Task<int>
created on one thread.
To run the Select
statement in paralell, you'll need to use PLINQ.
var tasks = actionItems.AsParallel().Select(t => DoSmthAsync());
This will produce your anticipated results.
You will then need to await Task.WhenAll(tasks);
to wait for the results of the tasks. Then you can access the result of each Task<int>
in your tasks
list with their respective Result
properties.
Upvotes: 3