Let's have the following situation
// method from class A
public async Task FooAsync()
{
return Task.Factory.StartNew(() => { //code_block_1 });
}
// method from class B
public async Task BarAsync()
{
return Task.Factory.StartNew(() => { //code_block_2 });
}
and an action method in a MVC controller
public async void SomeAction()
{
A a = new A();
B b = new B();
Task t1 = a.FooAsync();
Task t2 = b.BarAsync();
// Some other code 1
await Task.WhenAll(t1, t2);
// Some other code 2
}
And a request to that action is sent. How I think everything should work:
- A thread from the thread pool will be assigned to process the request
- The execution of SomeAction() starts in that thread. "a" and "b" are created.
- FooAsync() is called. Task.Factory.StartNew() is executed which creates new task for "//code_block_1". From that moment it's up to the TaskScheduler what thread from the thread pool will process the task. It could be the same thread executing "SomeAction" (in that case the execution of FooAsync would be synchronous) or another thread from the pool.
- BarAsync() is called. [Same as above]
- "// Some other code 1" is executed on the same thread on which SomeAction() started.
- await Task.WhenAll(t1, t2); creates a task which waits until both t1 and t2 have completed. Everything after the "await" ("// Some other code 2") is marked as "continuation" and the current thread is release back to the pool. Once both t1 and t2 have completed, the rest of the code can be processed by a thread from the pool (not necessarily the same thread which started processing SomeAction()).
And finally my question... Am I right? Am I wrong about something and what is it? And am I missing something?