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.
- Async void is for top-level event-handlers only, and event-like things. Don't use it elsewhere in your code.
- You can wrap events up in Task-returning APIs and await them. This can dramatically simplify code.
- 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.
- I gave this talk at Techready16 in Seattle, USA on 2013.02.05
- Watch videos online: Intro [5mins], Tip1: async void [20mins], Tip2: async and threads [16mins], Tip3: async-over-events [15mins]
- Download slides.pptx [6.3mb]
- Download script.docx [35k]
- Download VB source_code.zip [460k, requires VS2012 and Win8]
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 ModuleAnonymous
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 removedAnonymous
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-asyncAnonymous
July 18, 2013
Excellent Post. Also Visit www.msnetframework.comAnonymous
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?