0

If I put a few of the methods I'm calling, from my controller, into Task.Run what exactly is this doing? I'm not using an async function and I'm not using await.

...
FunctionOne();
FunctionTwo();
return View(FunctionThree().Result);
}

private void FunctionOne()
{
        Task.Run(() =>
        {
            ....
        }
}

private void FunctionTwo()
{
        Task.Run(() =>
        {
            ....
        }
}

private Task<MyType> FunctionThree()
{
        return Task.Run(() =>
        {
            ....
        }
}
wonea
  • 4,783
  • 17
  • 86
  • 139
J Hunt
  • 733
  • 1
  • 10
  • 21
  • 3
    It will start task 1 and 2 in the background, then block and wait for task 3 to complete, potentially deadlocking if you run this on the UI thread. If/when it completes, it will return the results from that task. Task 1 and 2 may still be running though. – Lasse V. Karlsen Jul 09 '15 at 14:53
  • Why would it deadlock? I'm not clear on this? Do you think this is a good way to speed things up? – J Hunt Jul 09 '15 at 14:54
  • 1
    See this question and answer: http://stackoverflow.com/questions/17248680/await-works-but-calling-task-result-hangs-deadlocks – Lasse V. Karlsen Jul 09 '15 at 15:03
  • Do you think this is a good practice? – J Hunt Jul 09 '15 at 15:03
  • 1
    Also, "is this a good way to speed things up?" I have no idea, what do you want to do? Do you really not want to know that task 1 has completed before starting task 2? And not wait for task 1 or 2 at all before starting task 3 or even returning from the method? If you don't, then yes, this looks like a good way to decouple separate jobs. – Lasse V. Karlsen Jul 09 '15 at 15:04
  • None of the tasks depend on the other. So I don't need to wait for any thing. Does this make things asynchronous even though I'm not using async? Are the background processes working at the same time or one as a time? – J Hunt Jul 09 '15 at 15:11
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/82839/discussion-between-j-hunt-and-lasse-v-karlsen). – J Hunt Jul 09 '15 at 15:14
  • Any idea why this doesn't work? private async Task FunctionThreeAsync() { return await FunctionThree(); } private Task FunctionThree() { return Task.Run(() => { .... }); } – J Hunt Jul 09 '15 at 15:49

1 Answers1

2

As @LasseVKarlsen explains, this code attempts to execute functions One, Two and Three in parallel. Task.Run immediately queues the specified work on the thread pool, and .Result will block the calling thread until its Task (and only its task) is complete.

This may or may not be a good design. Some things to consider:

  • You're using four threads from your thread pool to execute this action. If this action is under heavy load -- ie. it's called often -- the number of available threads in your pool could become a new bottleneck.
  • Functions One and Two have an essentially unbounded runtime since no client will be waiting on them. If too much logic is added to those functions, you could again run out of threads in your pool.
  • As @LasseVKarlsen mentions, this may lead to a deadlock.
  • If these are CPU-bound functions, then doing them in parallel may not buy you anything. (However, not waiting on One and Two might buy the client a lot.) If there are I/O operations underneath (eg. network calls, database calls, filesystem calls), you may want to look into Using an Asynchronous Controller in ASP.NET MVC instead.
  • As @StephenCleary notes, ASP.NET doesn't keep track of your threads. If a recycle occurs (say when you edit your web.config), it will always finish function Three as part of the request, but One and Two may be cancelled.

Whether these considerations suggest a change in your design is a question of what each function does, how long they take, and how important they are to your business logic.

Community
  • 1
  • 1
ladenedge
  • 13,197
  • 11
  • 60
  • 117