• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
CTU June 2011 - C# 5.0 - ASYNC & Await
 

CTU June 2011 - C# 5.0 - ASYNC & Await

on

  • 2,714 views

 

Statistics

Views

Total Views
2,714
Views on SlideShare
2,570
Embed Views
144

Actions

Likes
0
Downloads
43
Comments
0

6 Embeds 144

http://innovativesingapore.com 98
url_unknown 27
http://spiffy.sg 16
http://www.slideshare.net 1
http://www.spiffy.sg 1
http://spiffy1.capturepagedesigns.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • * Let's talk about this with waiters.* Read slowly: "A waiters job..."* Flaw in this. Can you see what it is? Obviously, a waiter can interleave!
  • [Joke: oh, you don’t want to go home early? Great. In that case I’ll dive into how it actually worked under the hood.]GOALS: To understand the “await” feature at a professional level -- that is, where the flow-of-control goes, which threads are involved, and how they communicate. Also to understand more deeply what asynchrony is. This will be enable you to be a better architect of asynchronous programs, e.g. Silverlight and ASP.This is the demo code, but I simplified it a little. I also split up “GetDiggAsync” and “await” onto separate lines. (Also I ported it over mostly to C#, apart from the XML literals).There are two existing threads allocated by the operating system. One is the UI thread for this process. The other is the “IO Completion Port” thread. Each of these threads has a queue associated with it.
  • When the user clicks a button, this inserts a “button-click-message” into the UI queue.The UI thread is in a while loop, checking for messages. When it gets this message it invokes the button-click handler.
  • The same thread makes function calls.When it calls the API “web.DownloadStringTaskAsync”, this returns immediately. It returns a Task, which I’ve called “downTask”. This task has not yet completed. The network stack will know to mark it as completed once the server’s response comes back.I should stress that “Task” does not mean a “BackgroundThreadTask”. The Task class is unrelated to questions of threads of execution.A “Task” is merely a “future” (C++), a “promise” – it’s an object that exists in one of three states, “InProgress” or “Completed(with result)” or “Faulted(with exception)”. It can be caused to transition from the first state to either of the other two. When this transition takes place, it will invoke any continuations that have been registered with it.And Task is a great unifying abstraction. That’s because it can stand for so many things – for a background worker thread on the current machine, or for a thread of execution on some remote database server, or for things that don’t take any threads at all like a button-click or a DMA transfer from disk to memory.Actually, if you’re familiar with the TPL, Task has a third state “Cancelled”. Through APIs we end up treating this state as equivalent to Faulted(with OperationCancelledException).
  • Now we execute the “await” operator. This does two things.First, it signs up a continuation onto downTask. For now I’ve written the continuation as “ui.Post{K1}” – not in real syntax. We’ll see later what it does. (Note that a task is allowed to have many continuations signed up on it.)Next, the first time we execute the “await” operator in an async method, we return a Task immediately. Once again, this task has not yet completed.
  • We execute the “await” operator. once again, this signs up a continuation onto the task, and returns to the calling thread (the UI thread).The UI thread can now resume it’s “while”-loop, checking for messages.If any other button-clicks happened (or mouse-drags or repaints or window-resizing) now, then they could be dealt with by the UI thread fine. This is where responsiveness comes in. (but it also brings in re-entrancy... imagine if the user clicked the same button again! then we’d start a second concurrent run through this button1_Click handler!)
  • Hey! A few seconds later, and the web services has delivered its answer to the IO Completion Port thread!
  • The IOCP thread knows which task was associated with that response.So it transitions it from the “Running” state to the “Completed with result ‘rss’” state. This causes it to execute the task’s continuation.
  • The continuation merely adds a message into the UI queue. Then it returns, allowing the IO Completion Port thread to resume its work.
  • The UI thread picks up the message from its queue, and responds by dispatching to K1, which assigns into the variable “rss”.
  • The code continues to execute. it comes to the “return” statement.(note that we have already returned the Task “diggTask” from this method. So you know the return statement is going to do something different...)
  • The “return” statement, in an async method, sets its returned task’s state to “Completed”, provides a result, and executes the task’s continuation.Once again, the continuation merely posts to the UI’s message-queue.
  • The method returns. Now the UI-thread can go back to its “while” loop, checking for messages in the queue. (There is one already!)
  • And the UI thread executes the method, puts the story into the text-box, and finishes.Note that ALL user code executed on the UI thread. All of it. That means the user never had to worry about the typical multi-threaded problems (semaphores, mutexes, semaphores, races, locks, ...)Also count how many threads were involved. Just the two that were already provided by the operating system. We didn’t create ANY additional threads.
  • These are some of the “Task Async Pattern” APIs that are included in the CTP.
  • We initially hadvar task2 = task.TimeoutAfter(1000);But we removed it because it didn’t have a clear-enough design. Would you want task2 to end with an OperationCancelledException after 1000ms? Or to end successfully? Both forms are useful. In the end, we figured that cancellation-after-1000ms was easier done like this:varcts = new CancellationTokenSource();cts.CancelAfter(1000)And we figured that successful-termination-after-1000ms was clearer if you wrote it out manually:var task2 = task.WhenAny(task, Task.Delay(1000))
  • There are three kinds of async methods. The difference between them is subtle.The difference between them is so subtle that we considered eliminating the first kind “void-returning asyncs” entirely. But that would have been wrong. That’s because every single async method you write will be invoked by someone who is also async, all the way up to the very top level of the callstack, to the “fire-and-forget” event handlers at the top like Button1_Click().So: every program that you’ll ever write will use void-returning asyncs. We have to accept that, and include it as a language feature.
  • Something to note here is that Task is composable.For instance, you can write a method which takes any two tasks and awaits until they’re both done.You can’t do that with the APM or the EAP. That’s because APM is just “a pair of methods with arbitrary parameters” and WebClient is just “a set of methods and events you have to call”. They’re not first-class citizens. They’re not things that you can pass as parameters to another method. But you can pass a Task directly to another method.That’s why the TAP is better.

CTU June 2011 - C# 5.0 - ASYNC & Await CTU June 2011 - C# 5.0 - ASYNC & Await Presentation Transcript