Partager via


Talk: The New Async Design Patterns

Talk: The New Async Design Patterns

Async involves some new concepts. They're not difficult; just unfamiliar. Over the past year I've been watching how people use it. This talk distils out the three top async patterns and anti-patterns.

  1. Async void is for top-level event-handlers only, and event-like things. Don't use it elsewhere in your code.
  2. You can wrap events up in Task-returning APIs and await them. This can dramatically simplify code.
  3. It's crucial to distinguish CPU-bound work (should be done on threadpool) from IO-bound work (which needn't).

If you understand the basic flow of control in an async method, then those three points all fall naturally into place.

 

 

 

 

 

 

 

PS. The first anti-pattern is "async void". People of course ask: "If it's so wrong, then why did you allow it?" That's a good question. I'll write a blog post solely on this question next week.

Comments

  • Anonymous
    February 17, 2013
    Great!!

  • Anonymous
    February 17, 2013
    Surely if you treat it like you should any new threaded operation and not allow exceptions to bubble up for example you'd be okay? Though why you'd want to await something that doesn't return anything seems silly - like a bad API design on the part of the person defining the void operation (presumably it's changing some internal state it shouldn't touch and simultaneously doing too much work in one place). Really the compiler should only allow calling async void's with an operator for fire and forget that just starts the method on a new thread, though the overhead to do that manually is quite low so I'm not sure the need was there, it is now you added 'await' simply for parity of implementation.

  • Anonymous
    February 26, 2013
    @Simon, I agree, it's bad API design to create an async void, since no one can await it. And it's also true that if you create an async void method, then it shouldn't leak exceptions. BUT The fire-and-forget would not have anything to do with threads. Remember that the async keyword by itself doesn't make things run on new threads. The ONLY way to run thing on a new thread is if you explicitly invoke an API to do that, e.g. Task.Run. So the fire-and-forget stuff would instead look like this: FooAsync().FireAndForget() ... Module ExtensionMethods    <System.Runtime.CompilerServices.Extension>    Async Sub FireAndForget(this As Task)        Try            Await this        Catch ex As Exception            ' here is a great opportunity to log the exception, or do something else with it        End Try    End Sub End Module

  • Anonymous
    March 03, 2013
    Hi, Anyone know if the video has been uploaded?

  • Anonymous
    March 11, 2013
    I've uploaded the videos now.

  • Anonymous
    March 12, 2013
    Please make that private async void Button1_Click(object sender, Eventargs e) {    Button1.Enabled(false); ...    Button1_Enabled(true); } otherwise simple re-entrancy is possible through the user clicking more than once. I suspect that this sort of thing will be a common problem in the future.

  • Anonymous
    March 13, 2013
    The comment has been removed

  • Anonymous
    March 13, 2013
    Great article by C# MVP Filip Ekberg on "Avoid shooting yourself in the foot with tasks and async" - covers similar issues about async void. blog.filipekberg.se/.../avoid-shooting-yourself-in-the-foot-with-tasks-and-async

  • Anonymous
    July 18, 2013
    Excellent Post. Also Visit www.msnetframework.com

  • Anonymous
    October 04, 2013
    When I see an async lambda whose handler does not take a Func<Task> and I cannot modify the handler. What should I do instead to stay unblocking? Maintain a concurrent dictionary where I add those tasks to and append a continuation task to each that removes the parent task from dictionary?