2

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:

  1. A thread from the thread pool will be assigned to process the request
  2. The execution of SomeAction() starts in that thread. "a" and "b" are created.
  3. 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.
  4. BarAsync() is called. [Same as above]
  5. "// Some other code 1" is executed on the same thread on which SomeAction() started.
  6. 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?

1 Answer 1

1

Yes, this is almost entirely accurate.

It could be the same thread executing "SomeAction"

If that was the case there would be no point in calling StartNew. This method is meant to create parallelism. It never inlines the task. You probably confused this with Wait inlining unstarted tasks.

Note, that because of the parallelism you initiated request processing will block 2 threads instead of one. Hadn't you used await it would have taken 3.

Sign up to request clarification or add additional context in comments.

4 Comments

So the better solution should be to use public async Task FooAsync() { await Task.Factory.StartNew(() => { //code_block_1 }); } ?
Why would that be better? (It is not. Trying to get you an insight here because I think you are capable of finding this out.)
If the //code_block_1 is an I/O operation (like database-related operation), then the thread should be released while waiting for it to complete? And there won't be any blocked threads?
The thread running FooAsync will be released in both cases immediately. Using await here does not affect anything in codeblock1. So you see there's no difference.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.