Your Cloud. Your Business. C# Async and Await Explained Jeremy Likness Principal Architect @JeremyLikness
Our Mission, Vision, and Values
Our Solutions
TODAY’S AGENDA 1. Why? Why do we need new keywords? 2. What? What exactly do async and await do? 3. How? How and when should async and await be used? 4. Q&A You have questions, I have answers
WHY?
WHY? Fundamentals • Once upon a time, an OS was created to run apps • These apps would run in a process • Processes would be segregated into app domains • App domains would run threads Process App Domain 1 •Thread 1 •Thread 2 App Domain 2 •Thread 3 •Thread 4 • Process is the running program, i.e. the .NET CLR host • App domains provide isolation from each other and can be uniquely configured, loaded, unloaded, and secured • Threads enable management of code execution
WHY? What’s in every thread … Thread kernel object (context) ~1KB Thread environment block (local storage data, graphics, exception handling) ~4KB – 8KB User mode stack ~1MB Kernel mode stack ~20KB
WHY? The life of one thread… Initialize memory Thread attach notifications sent to every DLL in the process Execute code Context Switch Execute Code Thread detach notifications Deallocate memory
WHY? Thread scheduling (1 core)
WHY? And to think …
DEMO: Threads
WHY? A Dip in the Thread Pool • We agree threads have overhead • To address this, the CLR introduces the thread pool • Starts out empty • As tasks are dispatched, threads are created • When thread is done, it is returned to the pool and recycled • Trade-offs exist: • Less overhead (memory pressure) • Less time to allocate/spin up a thread • However, fewer threads are scheduled concurrently
DEMO: Thread Pool
WHY? Tasks • Make it easier to deal with threads and the thread pool • Easy to wait • Automatic ability to cancel • Simple access to result • Chainable tasks (one starts when the other finishes) • Child tasks • Parallel functions
DEMO: Tasks
WHY? I/O Operations I/O Request Packet Make I/O Request Device Driver Queue Driver Does I/O Thread Goes to Sleep Thread Wakes Up
WHY? Synchronous: Two Threads Handle Request Blocked I/O Complete Handle Request Blocked I/O Complete
WHY? Asynchronous: One Thread Handle Request CompleteHandle Request Complete Asynchronous Asynchronous
DEMO: Asynchronous
WHAT?
What? async • Expecting to use await • Does not create new thread, always uses same thread as caller • After await may or may not use same thread (thread pool is involved, so threads are reusable) • If a SynchronizationContet exists, it will return to that thread • You can also modify this behavior using ConfigureAwait • Basically … think “yield” for threads!
What? Yield: a refresher
DEMO: Async
Best Practices • Never async void (use Task instead) • Exceptions can’t be caught so they are thrown in the context (if you have one!) • Made specifically for event handlers • If you must use for event handler, try to isolate the majority of code in another await that does return a Task • Never mix async and blocking code together • Task.Wait, Task.Result are generally bad ideas • Exception is a console application • From the necessary static main, promote to an async static main with a wait • Task.Wait should become Task.When
HOW?
How? • More impactful for I/O bound than compute-bound • Remember the Fibonacci examples? • Check this out …
DEMO: Async ThreadPool
How? • “I usually don’t work with multi-threading” • If you are working on the web, you are in a multi-threaded environment • If you are I/O bound, you should take advantage • Entity Framework now supports asynchronous methods! • The transformation is simple …
How? Asynchronous Controllers
How? Real World Results Source: http://blog.stevensanderson.com/2010/01/
How? Windows 8.x / 10 or whatever • Windows Runtime (WinRT) • IAsyncInfo • IAsyncAction • IAsyncOperation<TResult> • IAsyncActionWithProgress<TProgress> • IAsyncOperationWithProgress<TResult, TProgress> • ThreadPool.RunAsync • IAsyncInfo.AsTask()
Recap • You are always working with multi-threaded, don’t sell yourself short! • Compute-bound does not benefit as much from asynchronous as you might think, except to free the main context (typically your UI thread) • I/O has tremendous benefits • Async does not spin up a new thread. Instead, it establishes a state machine and makes the thread reusable and re- entrant • Await is not like Wait() because it doesn’t block and it allows you to recycle threads • If you have async I/O then USE IT! Async Task<> is your friend.
Deck and Source https://github.com/JeremyLikness/AsyncAwaitExplained
Questions? http://ivision.com/author/jlikness/ @JeremyLikness http://linkedin.com/in/jeremylikness http://plus.google.com/+jeremylikness http://stackoverflow.com/users/228918/jeremy-likness https://github.com/JeremyLikness http://csharperimage.jeremylikness.com/

C# Async/Await Explained

  • 1.
    Your Cloud. Your Business. C#Async and Await Explained Jeremy Likness Principal Architect @JeremyLikness
  • 2.
  • 3.
  • 4.
    TODAY’S AGENDA 1. Why?Why do we need new keywords? 2. What? What exactly do async and await do? 3. How? How and when should async and await be used? 4. Q&A You have questions, I have answers
  • 5.
  • 6.
    WHY? Fundamentals • Onceupon a time, an OS was created to run apps • These apps would run in a process • Processes would be segregated into app domains • App domains would run threads Process App Domain 1 •Thread 1 •Thread 2 App Domain 2 •Thread 3 •Thread 4 • Process is the running program, i.e. the .NET CLR host • App domains provide isolation from each other and can be uniquely configured, loaded, unloaded, and secured • Threads enable management of code execution
  • 7.
    WHY? What’s inevery thread … Thread kernel object (context) ~1KB Thread environment block (local storage data, graphics, exception handling) ~4KB – 8KB User mode stack ~1MB Kernel mode stack ~20KB
  • 8.
    WHY? The lifeof one thread… Initialize memory Thread attach notifications sent to every DLL in the process Execute code Context Switch Execute Code Thread detach notifications Deallocate memory
  • 9.
  • 10.
    WHY? And tothink …
  • 11.
  • 12.
    WHY? A Dipin the Thread Pool • We agree threads have overhead • To address this, the CLR introduces the thread pool • Starts out empty • As tasks are dispatched, threads are created • When thread is done, it is returned to the pool and recycled • Trade-offs exist: • Less overhead (memory pressure) • Less time to allocate/spin up a thread • However, fewer threads are scheduled concurrently
  • 13.
  • 14.
    WHY? Tasks • Makeit easier to deal with threads and the thread pool • Easy to wait • Automatic ability to cancel • Simple access to result • Chainable tasks (one starts when the other finishes) • Child tasks • Parallel functions
  • 15.
  • 16.
    WHY? I/O Operations I/O Request Packet MakeI/O Request Device Driver Queue Driver Does I/O Thread Goes to Sleep Thread Wakes Up
  • 17.
    WHY? Synchronous: TwoThreads Handle Request Blocked I/O Complete Handle Request Blocked I/O Complete
  • 18.
    WHY? Asynchronous: OneThread Handle Request CompleteHandle Request Complete Asynchronous Asynchronous
  • 19.
  • 20.
  • 21.
    What? async • Expectingto use await • Does not create new thread, always uses same thread as caller • After await may or may not use same thread (thread pool is involved, so threads are reusable) • If a SynchronizationContet exists, it will return to that thread • You can also modify this behavior using ConfigureAwait • Basically … think “yield” for threads!
  • 22.
    What? Yield: arefresher
  • 23.
  • 24.
    Best Practices • Neverasync void (use Task instead) • Exceptions can’t be caught so they are thrown in the context (if you have one!) • Made specifically for event handlers • If you must use for event handler, try to isolate the majority of code in another await that does return a Task • Never mix async and blocking code together • Task.Wait, Task.Result are generally bad ideas • Exception is a console application • From the necessary static main, promote to an async static main with a wait • Task.Wait should become Task.When
  • 25.
  • 26.
    How? • More impactfulfor I/O bound than compute-bound • Remember the Fibonacci examples? • Check this out …
  • 27.
  • 28.
    How? • “I usuallydon’t work with multi-threading” • If you are working on the web, you are in a multi-threaded environment • If you are I/O bound, you should take advantage • Entity Framework now supports asynchronous methods! • The transformation is simple …
  • 29.
  • 30.
    How? Real WorldResults Source: http://blog.stevensanderson.com/2010/01/
  • 31.
    How? Windows 8.x/ 10 or whatever • Windows Runtime (WinRT) • IAsyncInfo • IAsyncAction • IAsyncOperation<TResult> • IAsyncActionWithProgress<TProgress> • IAsyncOperationWithProgress<TResult, TProgress> • ThreadPool.RunAsync • IAsyncInfo.AsTask()
  • 32.
    Recap • You arealways working with multi-threaded, don’t sell yourself short! • Compute-bound does not benefit as much from asynchronous as you might think, except to free the main context (typically your UI thread) • I/O has tremendous benefits • Async does not spin up a new thread. Instead, it establishes a state machine and makes the thread reusable and re- entrant • Await is not like Wait() because it doesn’t block and it allows you to recycle threads • If you have async I/O then USE IT! Async Task<> is your friend.
  • 33.
  • 34.

Editor's Notes

  • #12 01Threads
  • #14 02ManyTasksNoThreadPool, 03ManyThreadsThreadPool
  • #16 04Tasks, 05Parallel
  • #20 06Asynchronous
  • #24 07AsyncAwait, 07bAsyncAwaitWithContext, 08NoAsyncAwait
  • #28 09AsyncThreadPool