RSS 2.0 | Atom 1.0

Sign In


# Friday, August 29, 2008
No, really, the Event-based Asynchronous Pattern IS bad
Came across this:

His main point is that async total sucks, but that "Events don’t necessarily make async code tragically unreadable!" As a demonstration, he shows some simple async HTTP code without full or exception continuations. His code just enforces my point.

At any rate, yes, sure, if your continuation code isn't too related to your calling code, events can work. I mentioned this in my post: "events are a bad choice for code that is not loosely coupled" followed with "sometimes a simple delegate field would be a better choice". Indeed, looking at Mike's sample code, it seems as if using a simple delegate field would allow some nice refactoring.

But a point of the Event-based Asynchronous Pattern is, and I quote, to "Wait for resources to become available without stopping ("hanging") your application". So basically, you want to take an existing method, say, in response to a user action, but you can't let it block. This is exactly perfect for a continuation based approach and not so much for a loosely-coupled event-based approach. The act of "firing" an event should indicate that you're letting _other listeners_ (notice the plural) know when you did something.

More on when events are appropriate: Say you're listening for SNMP messages and when you receive one, you let "everyone" know that you did. You don't care what they do with the result, and they just go off on their own. Events can work. Or, take, for example, the BackgroundWorker. The BackgroundWorker doesn't help thread your blocking code, it just pushes the block to a background thread you don't care about. Your HTTP code will still be all sync, and you'll still burn a thread. BackgroundWorker main help is that it coordinates back to your "UI" thread, since many UI frameworks have strong thread affinity and will crash otherwise.

But that was the whole point
The event async pattern, specifically in things like Silverlight, is completely aimed at *not letting the thread block*. That's the _only_ problem it is trying to solve. Silverlight only forces this because the main thread is the UI thread, and they won't want the browser hanging by dumb apps that don't put the block on a background thread. If they didn't want to do continuations, they could have at least kept the sync APIs, and thrown an exception if called from the main thread (thus letting people who know what they're doing not have to deal with the ugly event syntax).

BTW, F# kicks the crap out of your language
I didn't mention it in my previous event post, but F#'s computation expressions let you deal with continuations in a totally sexy way. H.H. Don Syme, writes about it here: Introducing F# Asynchronous Workflows. You learn F# if you don't know it. But just to demonstrate, here's an example from that introduction:

    let AsyncHttp(url:string) =

        async {  // Create the web request object

                 let req = WebRequest.Create(url)


                 // Get the response, asynchronously

                 let! rsp = req.GetResponseAsync()


                 // Grab the response stream and a reader. Clean up when we're done

                 use stream = rsp.GetResponseStream()

                 use reader = new System.IO.StreamReader(stream)


                 // synchronous read-to-end

                 return reader.ReadToEnd() }

The let! binding handles things asynchronously; the rest of the body becomes a continuation. If that isn't superior to any C# approach and doesn't make async easy, I don't know what would.

Code | FSharp
Friday, August 29, 2008 9:03:55 PM UTC  #    Comments [0]  |  Trackback

Please login with either your OpenID above, or your details below.
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

Live Comment Preview