Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write an "awaitable" method?

Tags:

c#

async-await

I'm finally looking into the async & await keywords, which I kind of "get", but all the examples I've seen call async methods in the .Net framework, e.g. this one, which calls HttpClient.GetStringAsync().

What I'm not so clear on is what goes on in such a method, and how I would write my own "awaitable" method. Is it as simple as wrapping the code that I want to run asynchronously in a Task and returning that?

like image 385
Andrew Stephens Avatar asked Feb 11 '14 11:02

Andrew Stephens


People also ask

What is awaitable method?

What is an "awaitable" method? These are methods that return Task or Task<T> (and they can also return "void" and there are some other awaitables, but we'll just worry about Tasks today). You can get the code download for this article on GitHub: https://github.com/jeremybytes/using-task.

What is Awaitable in C#?

The await keyword in C# programming language is used to suspend all async methods enclosed until the point where the operations presented by the asynchronous method are completed. In order or a developer to call multiple functions in an asynchronous way, async and await are highly used and recommended.


2 Answers

It's as simple as

Task.Run(() => ExpensiveTask()); 

To make it an awaitable method:

public Task ExpensiveTaskAsync() {     return Task.Run(() => ExpensiveTask()); } 

The important thing here is to return a task. The method doesn't even have to be marked async. (Just read a little bit further for it to come into the picture)

Now this can be called as

async public void DoStuff() {     PrepareExpensiveTask();     await ExpensiveTaskAsync();     UseResultsOfExpensiveTask(); } 

Note that here the method signature says async, since the method may return control to the caller until ExpensiveTaskAsync() returns. Also, expensive in this case means time-consuming, like a web request or similar. To send off heavy computation to another thread, it is usually better to use the "old" approaches, i.e. System.ComponentModel.BackgroundWorker for GUI applications or System.Threading.Thread.

like image 109
Janis F Avatar answered Sep 24 '22 19:09

Janis F


How I would write my own "awaitable" method? Is it as simple as wrapping the code that I want to run asynchronously in a Task and returning that?

That is one option, but it's most likely not what you want to do, because it doesn't actually give you many of the advantages of asynchronous code. For more details, see Stephen Toub's Should I expose asynchronous wrappers for synchronous methods?

In general, methods are not awaitable, types are. If you want to be able to write something like await MyMethod(), then MyMethod() has to return Task, Task<T> or a custom awaitable type. Using a custom type is a rare and advanced scenario; using Task, you have several options:

  • Write your method using async and await. This is useful for composing actions asynchronously, but it can't be used for the inner-most awaitable calls.
  • Create the Task using one of the methods on Task, like Task.Run() or Task.FromAsync().
  • Use TaskCompletionSource. This is the most general approach, it can be used to create awaitable methods from anything that will happen in the future.
like image 38
svick Avatar answered Sep 24 '22 19:09

svick