Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use async await or task?

You have built a complex calculation algorithm. It takes quite some time to complete and you want to make sure that your application remains responsive. What do you do?

  • A. Use async/await.
  • B. Run the code synchronously.
  • C. Use Task.Run.
  • D. Use a BackgroundWorker.

The answer is C. However, can someone please explain why A) is incorrect? Because the question does not say that the complex algorithm is CPU bound. If it was CPU bound, then we will have to use Tasks (a reasoning I don't understand very well too, though I know that tasks do help cause the current thread to get suspended until they complete). Additionally, please explain how to decide when to use async/await, and use Tasks.

like image 806
user3509153 Avatar asked Jul 24 '14 06:07

user3509153


People also ask

What is difference between Task and async await?

async, await, and TaskThe await keyword waits for the async method until it returns a value. So the main application thread stops there until it receives a return value. The Task class represents an asynchronous operation and Task<TResult> generic class represents an operation that can return a value.

When should you use async await?

Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.

Is it OK to not await async?

No. An await is an "asynchronous wait". The method will wait for it, but the UI thread will not.

Does async await improve performance?

The main benefits of asynchronous programming using async / await include the following: Increase the performance and responsiveness of your application, particularly when you have long-running operations that do not require to block the execution.


2 Answers

What do you do?

A. Use async/await.

B. Run the code synchronously.

C. Use Task.Run.

D. Use a BackgroundWorker.

The async/await feature in C# 5.0 was implemented in order to make asynchronous code "as easy" as writing synchronous code. If you look into WinAPI, you'll see that almost all async endpoints expose a fully async api, meaning there is no thread. Looking further you'll notice that those same endpoints are doing I/O bound operations.

Assuming your algorithm is CPU bound, and is written in a manner which allows effective computation across multiple processors (for example, your algorithm doesn't have any shared state which needs synchronization), you can take advantage of the Task Parallel Library introduced in .NET 4.0. The TPL provides an abstraction over the ThreadPool, which in turn attempts to offload work evenly in a multiprocessor environment.

The await keyword can be used on any awaitable object, meaning that object implements the GetAwaiter method. You would want to use await when you are using an awaitable and want execution to resume when that awaitable is done doing its work. A Task implements the awaitable pattern and is used to describe a unit of work which will be completed in the future. You can use Task.Run and await, when you want to offload a unit of work on a worker thread and you want to return control to the calling method until that work is done.

Another way of dispatching CPU bound work across multiple processors is to use the Parallel class which exposes Parallel.For and Parallel.ForEach.

On a side note, a BackgroundWorker can also be used to offload work on a background thread, if thats what the person asking the question was after. It is recommended to use the TPL since .NET 4.0 was released.

To conclude, using the Task Parallel Library is the recommended way to offload work to background threads. You may use them in combination with the Parallel library to maximize the parallelism of your algorithm. After doing so, test your code to make sure the overhead of using multiple threads doesn't outweigh the time it takes to run your algo synchronously.

Edit

As Stephan mentioned in the comment, you may combine both Parallel.ForEach and Task.Run to offload a parallel loop inside a background thread:

var task = Task.Run(() => Parallel.ForEach(.. //Loop here));
like image 150
Yuval Itzchakov Avatar answered Nov 08 '22 11:11

Yuval Itzchakov


I suppose "calculation" implies CPU bound algorithm in the absence of other information. If the algorithm is IO bound async/await is not only acceptable but the correct answer.

like image 27
Stilgar Avatar answered Nov 08 '22 11:11

Stilgar