To those who have already read the article
If you have already read the article and only want to know what's new, click here. The second update is here.Background
I already wrote the article Yield Return Could Be Better and I must say thatasync/await
could be better if a stack-saving mechanism was implemented to do real cooperative threading. I am not saying that the async/await
is a bad thing, but it could be added without compiler changes (enabling any .NET compiler to use it) and maybe adding keywords to make its usage explicit. Different from the other time, I will not only talk about the advantages, I will provide a sample implementation of a stacksaver and show its benefits.Understanding the async/await pair
The async/await was planned for .NET 5 but it is already available in the 4.5 CTP. Its promise is to make asynchronous code easier to write, which it indeed does.But my problem with it is: Why do people want to use the asynchronous pattern to begin with?
The main reason is: To keep the UI responsive.
We can already maintain the UI responsive using secondary threads. So, what's the real difference?
Well, let's see this pseudo-code:
using(var reader = ExecuteReader())
while(reader.ReadRecord())
listbox.Items.Add(reader.Current)
Very simple, a reader is created and while there are records, they are added to a listbox. But imagine that it has 60 records, and that each ReadRecord
takes one second to complete. If you put that code in the Click of a Button, your UI will freeze for an entire minute.If you put that code in a secondary thread, you will have problems when adding the items to the listbox, so you will need to use something like
listbox.Dispatcher.Invoke
to really update the listbox.With the new
await
keyword, your method will need to be marked as async
and you will need to change the while
line, like this:while(await reader.ReadRecordAsync())
And your UI will be responsible.That's magic!
Your UI became responsible by a simple call toawait
?And what's that
ReadRecordAsync
?Well, here is where the complexity really lives. The
await
is, in fact, registering a continuation and then allowing the actual method to finish immediately (in the case of a Button Click, the thread is free to further process UI messages). Everything that comes after await
will be stored in another method, and any data used before and after the await
keyword will live in another class created by the compiler and passed as a parameter to that continuation.Then there is the implementation of
ReadRecordAsync
. This one may be considered the hardest part, as it may use some kind of real asynchronous completion (like IO completion ports of the Operating System) or it will still use a secondary thread, like a ThreadPool
thread.
Comments
Post a Comment