tabs ↹ over ␣ ␣ ␣ spaces

by Jiří {x2} Činčura

The magic of "async" keyword

25 Oct 2014 C#, Multithreading/Parallelism/Asynchronous/Concurrency

In last couple of weeks I was again confronted number of times with something “asynchronous”. In this post I don’t want to argue about CPU-bound and IO-bound operations with respect to “asynchronous” word. What I’ll talk about is the async keyword. Because it looks like there’s still confusion.

Short story. The async keyword does nothing with your code (related to asynchronicity). That’s it. I said it.

Long story. The async keyword is there only to help compatibility and compiler. When you’re writing something like the compiler you’re not only thinking about backward compatibility (that’s a must), you’re also thinking about forward compatibility (as much as possible). And that’s exactly it. If you compile your old code with the new compiler you’d like to - very likely - to have the same behavior of code (maybe bit faster ;)).

But because C# 5 added the new await keyword it might collide with your previous code. Looks like theory? Let me show you some code.

static Task<int> Test()
	return await (Task.FromResult(6));

static Task<int> await(Task t)
	Console.WriteLine("No async, huh? ;)");
	return Task.FromResult(-1);

This is perfectly valid C# 4 code, isn’t it? Yes, naming the method await does not match generally used formatting, but who cares?

Now imagine C# 5 with just await keyword. Compiling this code would result in different behavior. Either the compiler could complain about collision on await method or silently compile it one ot the other way. Not good. You’d have to change your code to reach the behavior you wanted (or use some crazy switches). But if you actually try to compile this code using C# 5 it works fine.

Once you add the async keyword it changes.

static async Task<int> Test()
	return await (Task.FromResult(6));

See the change? The async keyword. Now you actually changed the code and you are aware of behavior change (or you should be).

So what the async actually did? It just tells the compiler: “If you see await consider it keyword.”. And because you did the change, you’re changing the code and so the forward compatibility is not broken.

No magic. Sorry.