tags:

views:

97

answers:

5

Hi,

Say I have 4 classes

  • ControllerClass
  • MethodClass1
  • MethodClass2
  • MethodClass3

and each MethodClass has an asynchronous method DoStuff() and each has a CompletedEvent.

The ControllerClass is responsible for invoking the 3 asynchronous methods on the 3 MethodClasses in a particular order.

So ControllerClass invokes MethodClass1.DoStuff() and subscribes to MethodClass1.CompletedEvent. When that event is fired, ControllerClass invokes MethodClass2.DoStuff() and subscribes to MethodClass2.CompletedEvent. When that event is fired, the ControllerClass invokes MethodClass3.DoStuff()

Is there a best practice for a situation like this? Is this bad design?

I believe it is because

  • I am finding it hard to unit test (a sure sign)
  • It is not easy to change the order
  • I have an uneasy, code-smell feeling about it

What are the alternatives in a situation like this?

Note: I am targeting the .NET 2.0 framework

A: 

What version of .NET are we using? In .NET 4.0 there is the Task class which you can use to fire tasks, and change the order very easily.

A good example is here: http://blogs.msdn.com/pfxteam/

You can see how you can queue up tasks.

Snake
This belongs to the Task Parallel Library: http://msdn.microsoft.com/en-us/library/dd460717.aspx
Oliver
@Oliver: PFX is part of .NET 4.0 :)
Snake
Unfortunately it is .NET 2.0 in this case...
Peter Kelly
+1  A: 

Jeff Richter has a great article about using enumerators to simplify APM code. Microsoft CCR also uses a similar technique. Worth investigating:

http://msdn.microsoft.com/en-us/magazine/cc546608.aspx

spender
His AsyncEnumerator is a simple version of the Microsoft CCR, which is supersede by the Task Parallel Library: http://msdn.microsoft.com/en-us/library/dd460717.aspx
Oliver
@spender: Thanks for the link, I'll check that out. I should have stated I am targeting .NET 2.0. I'll update my original question.
Peter Kelly
@Oliver: as far as I know, task parallel library doesn't supersede the ccr, it can be used side by side and they have different characteristics. Ccr is light weight async processing and messaging, tpl is more heavy duty paralyzing big algorithms.
Toad
A: 

Since the three methods you are using needed to be run in a particular order and they need to wait for each other, why do you bother calling them asynchronously? Just make simple synchronous calls.

Cagdas
The methods themselves start asynchronous work so they will return to the caller immediately. The only way to know something interesting has happened is to subscribe to the Completed event.
Peter Kelly
Perhaps the code is heavily concurrent (on a server?), in which case blocking the thread for any amount of time would be inadvisable as it would require many threads that sit around doing nothing. In my experience, NOT using APM in this situation is a really good way to kill server performance.
spender
+1  A: 

If you have access to the code of the classes that you are invoking, and also have the freedom to change it, why not wrap it up in a handler (implementing Chain of Responsibility pattern). You can then define successor for each method. That will keep the complexity low with a higher flexibility.

Kangkan
That's interesting approach actually. I like being able to set the successor in this pattern. +1 there anyway.
Peter Kelly
+1  A: 

There's no point in doing it this way. Call one helper method asynchronously. It should call the three methods you are now running asynchronously. Sequencing them is now simple and you only have one async method to worry about. More efficient too, you are not starting and switching between threads anymore. It actually takes less time.

Hans Passant
Thanks Hans. So wrap the methods in one async helper method and then let that worry about the ordering of the other 3 methods etc. It would simplify things from the caller alright.
Peter Kelly