I’m trying to understand async await in the simplest form. I want to create a very simple method that adds two numbers for the sake of this example, granted, it’s no processing time at all, it’s just a matter of formulating an example here.
private async Task DoWork1Async() { int result = 1 + 2; }
private async Task DoWork2Async() { Task.Run( () => { int result = 1 + 2; }); }
If I await DoWork1Async() will the code run synchronously or asynchronously?
DoWork1Async()
Do I need to wrap the sync code with Task.Run to make the method awaitable AND asynchronous so as not to block the UI thread?
Task.Run
I’m trying to figure out if my method is a Task or returns Task<T> do I need to wrap the code with Task.Run to make it asynchronous.
Task
Task<T>
Stupid question I’m sure but I see examples on the net where people are awaiting code that has nothing async within and not wrapped in a Task.Run or StartNew.
StartNew
First, let’s clear up some terminology: “asynchronous” (async) means that it may yield control back to the calling thread before it starts. In an async method, those “yield” points are await expressions.
async
await
This is very different than the term “asynchronous”, as (mis)used by the MSDN documentation for years to mean “executes on a background thread”.
To futher confuse the issue, async is very different than “awaitable”; there are some async methods whose return types are not awaitable, and many methods returning awaitable types that are not async.
Enough about what they aren’t ; here’s what they are :
void
So, if we reformulate your question to “how can I run an operation on a background thread in a way that it’s awaitable”, the answer is to use Task.Run:
private Task<int> DoWorkAsync() // No async because the method does not need await { return Task.Run(() => { return 1 + 2; }); }
(But this pattern is a poor approach; see below).
But if your question is “how do I create an async method that can yield back to its caller instead of blocking”, the answer is to declare the method async and use await for its “yielding” points:
private async Task<int> GetWebPageHtmlSizeAsync() { var client = new HttpClient(); var html = await client.GetAsync("http://www.example.com/"); return html.Length; }
So, the basic pattern of things is to have async code depend on “awaitables” in its await expressions. These “awaitables” can be other async methods or just regular methods returning awaitables. Regular methods returning Task/Task<T> can use Task.Run to execute code on a background thread, or (more commonly) they can use TaskCompletionSource<T> or one of its shortcuts (TaskFactory.FromAsync, Task.FromResult, etc). I don’t recommend wrapping an entire method in Task.Run; synchronous methods should have synchronous signatures, and it should be left up to the consumer whether it should be wrapped in a Task.Run:
TaskCompletionSource<T>
TaskFactory.FromAsync
Task.FromResult
private int DoWork() { return 1 + 2; } private void MoreSynchronousProcessing() { // Execute it directly (synchronously), since we are also a synchronous method. var result = DoWork(); ... } private async Task DoVariousThingsFromTheUIThreadAsync() { // I have a bunch of async work to do, and I am executed on the UI thread. var result = await Task.Run(() => DoWork()); ... }
I have an async/await intro on my blog; at the end are some good followup resources. The MSDN docs for async are unusually good, too.