0

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?

Basil Kosovan
  • 888
  • 1
  • 7
  • 30

2 Answers2

2

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.

Community
  • 1
  • 1
Victor Wilson
  • 1,720
  • 1
  • 11
  • 22
  • The `AsParallel` will only **start** the tasks in parallel. The OP is probably interested in the whole execution of the tasks, from start to completion. – Theodor Zoulias Dec 12 '19 at 21:02
  • It seems like his priority is that computation occurs on multiple threads. I've edited my post to include a method to retrieve the results of the tasks. – Victor Wilson Dec 12 '19 at 21:29
1

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 almost all built-in 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 this is unusual and not recommended.

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, not a materialized collection. The actual materialization of the tasks happens when you call the method Task.WhenAll(tasks).

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104