views:

277

answers:

3

Hi,

I have design problem regarding async calls to method.

I'd like to know best/good pattern to call async method, which calls another async method, which calls another async method :)

In other words, I have WCF service reference created with async methods and I want to call them from another async method which is called by other async method. All this for non blocking GUI.

Thanks!

A: 

Switch to F#, where calling/composing async methods is nearly as easy as the sync ones.

(See also

LINQ for sequential async code in C#: http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!208.entry

F# on the server side (async comparison with C#): http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!1847.entry

F# on the client side (easy): http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!1842.entry

)

Brian
2 reasons this is a bad answer: 1) You're spamming your own blog. 2) answers with just links to other sites are not the goal of SO. At least add a short summary in-line.
Henk Holterman
+3  A: 

If your only goal is to have a non blocking GUI then the multiple levels are unnecessary. Once your toplevel method runs in the background, your GUI is freed. Using multiple levels does bring extra complexity.

There can be other reasons (performance) to call the lower level methods async, but it depends. Do you need to wait for results later on?

So I don't think there is a 'pattern' here.

Henk Holterman
Though it may take a little effort to 'rendezvous with the final result' when it's all completed.
Brian
Multiple levels are required by architecture. It's separation of concerns. What about this?
michajas
@michajas: Multiple levels is separation of concerns. Making them async adds complexity and _mixing_ of concerns (IAsyncResult)
Henk Holterman
@Henk: Ok, so do you think that better way would be to make WCF call synchronous and make only top call (call from GUI) async?
michajas
@michajas: In general: Yes. There could be exceptions, you'd have to provide more details.
Henk Holterman
@Henk: at the same time, the complexity is only there because the language doesn't do it natively. A language that did it natively, like Erlang, wouldn't suffer the same complexity issues. Given that one wants the feature, it's hard to avoid the complexity. But you can return other things than IAsyncResult; like Lazy<T> (aka Future<T>)... Or as I do in some code; return a 3-tuple of cancellation token, progress publisher (with reactive extensions) and IEnumerable<T>, as IEnumerable<T> is lazy per definition.
Henrik
A: 

One example of when it would be good to have multiple levels would be when creating asynchronous controllers in a MVC framework like MonoRail or MS MVC. The end thing that calls into something IO-blocking, such as SqlCommand from System.Data.SqlClient or some socket, would put the IO operand on an IO completion port: http://msdn.microsoft.com/library/aa365198, which would save the managed/unmanaged thread's quanta for something more useful.

If you write classes that return IAsyncResult, then you are not far away from implementing co-routines. Here's a good article about how asynchronous programming can be used with coroutines: http://blogs.msdn.com/b/pfxteam/archive/2009/06/30/9809774.aspx.

Caliburn, a WPF framework supports co-routines natively. The task parallel library, released with .Net 4, has given its task the IAsyncResult interface. [If you are at 3.5 then you might need to create your own implementation (they are pretty simple to make, just implement the interface).] Co-routines are a way of using the compiler re-writes of IEnumerable to push IAsyncResults to a stack of things to do (as seen from the "async manager").

F# async (like seen in the down-voted answer) uses a monad (as monadic as they get on the CLR) to move the state of the asynchronous request from the Begin* to End* methods. The compilers both this into nested lambda expressions/SelectMany.

Henrik