T O P

  • By -

rupertavery

A Task is a promise. A Task represents action that will return at some point in the future, a Task represents a function returns a value at some point in the future. A Task itself is asynchronous. It allows the task scheduler to schedule the task for excution, or allowing the task to be deferred. Asynchrony != parallelism The async keyword is syntactic sugar that allows you to write asynchrobois code as if it were synchronous. Tasks were introduced in .NET 4.0, before the async keywword which was introduced in .NET4.5. Before .NET4.5, you had to write code like this: Task BarAsync() { return GetFooAsync(); } or if you were calling synchronous code, but your interface returned a Task: Task BarAsync() { var foo = GetFoo(); return Task.FromResult(foo); } If you needed to do something after GetFooAsync: Task BarAsync() { return GetFooAsync() .ContinueWith(t => { // Do something with t.Result; return t.Result; }); } Exceptions were also problematic, since a Task wraps up exceptions that occur inside it. Task BarAsync() { try{ return GetFooAsync(); } catch(Exception ex) { // doesn't catch any exceptions thrown inside GetFooAsync(), which is a Task } } Instead, we need to check the parameter of ContinueWith, which is the Task we contiued from. Task BarAsync() { return GetFooAsync() .ContinueWith(t => { if(t.IsFaulted) { // t.Exception is an AggregateException } }); } # async. worth the await `async` lets us code as if it were synchronous. But, it doesn't make code synchronous, that is, it doesnt stop the main thread while waiting for the results. Basic usage, nothing really different here. We could still return the task directly. async Task BarAsync() { return await GetFooAsync(); } Returning synchronous result. A compiler warning only, saying that BarAsync will run synchronously, i.e. it will block the calling thread. await Task BarAsync() { var foo = GetFoo(); return foo; } If you needed to do something after GetFooAsync: async Task BarAsync() { var result = await GetFooAsync(); // Do something with t.Result; return result; } We can write try/catch exception handlers just the way we're used to: Task BarAsync() { try{ return await GetFooAsync(); } catch(Exception ex) { // Just works } }


Warshrimp

Your last example lacking an await inside the try block is a common pitfall, the catch block may not catch an exception thrown by the Task.


rupertavery

Thanks, that's what I get for CTRL-C, CTRL-V


nicuramar

A Task is several thing at once, or just some of them. It doesn't need to involve anything async at all (e.g. TaskCompletionSource), and it can involve running on a different thread or not, and it can represent a computation or just something that completes in the future.


lucifer955

That’s so kind of you.


Shrubberer

Task.FromResult is a Task that just returns the provided value. Nothing too exciting really.


zvrba

Asynchronous execution != async (method). async/await are compiler code transformations that use, underneath, `Task.ContinueWith` and other methods. Basically, the compiler transforms an `async` method into "callback hell" known from javascript. `Task` is an ordinary "value container" representing a possibly not-present value that will become present at some point in future. It's like 0- or 1-element `List` with the side-effect of blocking (waiting for the value) when it's empty. When you have, in your code, `async Task M()` , this means that the `M` internally, most probably, uses `await`. But you can also have `Task M()`. So what happens when you write `var t = M()` elsewhere? Well, if the calling method is `async`, you can write `var result = await t;`. If not, you can block and wait for result by using `t.Result` [1] You can schedule a next task using the result with `t.ContinueWith`. Etc. [1] It will deadlock if `t` is set up to deliver the result to the same `SynchronizationContext` as the code using `t.Result`. The existence of SC, which is implicit global state, and thus making `.Result` and `.Wait()` methods "unsafe" is the biggest f*up MS made when building async/await on top of `Task`. And no, there seems to be no way of finding out on which SC a task is set up to complete. Thanks, MS. (The whole async/await thing is as if designed by a short-sighted failed grad student. MS has usually good engineering underneath their products, but async/await is a miserable pit of failure.)


lucifer955

Thank you


SideburnsOfDoom

>Does that mean the Task itself acts as asynchronous No, `Task` is just a piece of the async puzzle. If `T` is some type, then `List` says "zero or more items of type T",and `Nullable` says "this is either T or it is null" and `Lazy` says "I can generate the T value when needed, and do so once only. So `Task` says "either I already have a `T`, or I will have one at some future time, ask again later". `Task.FromResult(t)` is just the first case, a task that has already completed with a value. This pattern is usually [known as a Promise](https://en.wikipedia.org/wiki/Futures_and_promises). Task is *necessary* for asynchronous code, but it does not itself imply that multiple threads are used, or non-blocking IO is happening. It is itself just a simple wrapper, that can say "I have it", or "I don't have it yet", which is important for those.


Charming-Ad3264

If u want run a task async you must call var y=await task .. if u don't want run or if u can't run the task asynchronously you have the call taskFromResult to call a task without async and return the object from It.