Waiting for a call to a task created with Task.Run ()

Why is this possible in C #?

var task = Task.Run (...);
await task;


Isn't it supposed Task.Run()

for cpu related code? Does it make sense to call await

for this?

Ie, after the call Task.Run

I understand that the task is running on a different thread of the thread pool. What is the purpose of the challenge await

? Doesn't make sense to just name it task.Wait()


In the last question, the first impression was that it await

is solely for use with methods async

. Is it common to use this for the task being returned Task.Run()


EDIT. It also makes me wonder why we have Task.Wait ()

rather than Task.Await()

. I mean, why is the method used for Wait()

and keyworkd for await

. Wouldn't it be more consistent to use the method in both cases?


source to share

5 answers

There Wait

would be no point in using it. It doesn't make sense to start a new thread to work if you just have another thread sitting there waiting for nothing. The only reasonable option for these two is await

. Waiting for a task is perfectly reasonable as it allows the original thread to continue executing.

This makes sense for await

any type Task

(in the right context), no matter where it comes from. There is nothing special about the expected methods async

. In fact, every single asynchronous program should have asynchronous methods that don't use the keyword async

; if everyone await

expects a method async

, you never have to start.



There are some good answers here, but from a more philosophical point of view ...

If you have a lot of CPU bound work, a parallel task library is usually the best solution, i.e. Parallel

or parallel LINQ.

If you have a job with reference to the I / O, the best solution is usually async

, and await

code that is built around the natural asynchronous implementations (for example, Task.Factory.FromAsync



is a way of executing one piece of cpu-related code and treating it as asynchronous from the perspective of the calling thread. Ie if you want to work with the CPU but not mess with the UI.

Construct await Task.Run

is a way to transcend two worlds: ask the UI thread queue to run from the CPU and process it asynchronously. This IMO is the best way for asynchronous and parallel code like await Task.Run(() => Parallel.ForEach(...))


why method is used for Wait () and keyword for wait.

One of the reasons it await

is a keyword is because they wanted to enable pattern matching. Tasks are not the only ones "pending". WinRT has their own idea of "asynchronous operation" that await observed Rx sequence of waiting Task.Yield

does not return the required task, and it allows you, if necessary, to create their own expectations (for example, if you want to avoid exposure Task

to high-performance socket applications



Yes, it is common and recommended. await

allows you to wait for a task (or any expected) to be completed asynchronously . It is true that it is mainly used for naturally asynchronous operations (like I / O), but it is also used to offload work being done in another thread using Task.Run

and wait for asynchronous waiting to complete.

The use Wait

not only blocks the calling thread and thus defeats the purpose of use Task.Run

in the first place, it can also lead to deadlocks in a GUI environment with a single threaded synchronization context.

One of the last questions, my first impression was that the wait is meant to be used exclusively with asynchronous methods

Whether or not a method is actually marked with a modifier async

is an implementation detail, and most of the "root" restore methods in .Net are not actually async

ones ( Task.Delay

a good example for this).



Doesn't make sense to just call task.Wait ()?

No, if you call Wait

, you are using two threads there, one of the worker threads from the ThreadPool is working for you (given the task is CPU bound) and also your calling thread will be blocked.

Why would you need to block the calling thread? The result will be too bad if the calling thread is a UI thread! Also if you call Task.Run

, then Task.Wait

, you make it worse too. This is no better than calling the delegate synchronously. There is no point in calling Wait

immediately after starting a Task.

You should almost never use Wait

, always prefer await

and free the calling thread.



This is very common and useful for cases like (much simplified: production code for example for handling exceptions):

async void OnButtonClicked()
   //... Get information from UI controls ...
   var results = await Task.Run(CpuBoundWorkThatShouldntBlockUI);
   //... Update UI based on results from work run in the background ...


As far as commenting on your later edits, "awaiting" is not a method call. This is the keyword (only allowed in a method marked "async" for clarity) that the compiler uses to decide how to implement that method. Under the hood, this involves rewriting the method procedure as a state machine that can be paused every time you use the "wait" keyword and then resumed when whatever it is expecting returns to indicate that it is done. This is a simplified description (exception propagation and other details complicate things), but the key point is that "waiting" is much more than just calling a method on a task.

In previous versions of C #, the closest construct to this async / await magic was to use yield return for implementation IEnumerable<T>

. For both enums and asynchronous methods, you need a way to pause and resume the method. Asynchronous / pending keywords (and related compiler support) start with this basic idea of ​​a resumable method and then add some powerful features like automatic exception propagation, dispatching callbacks through a sync context (mostly useful for saving code on a custom thread) interface) and automatically implement all the glue code to set the continuation callback logic.



All Articles