Geeks With Blogs
Running with Code Like scissors, only more dangerous

I've made allusions to my current project several times, and while I can't discuss it with specifics, but I'm working with hardware; part of the device is an armature that extends to receive a piece of equipment from the user, and then it will once again extend to re-dispense the object at the conclusion of its task.  The armature controller hardware is strictly asynchronous, and as such, I decided initially to write it with asynchronous callbacks.  It's fairly straightfoward to have a method called "Extend" and an event called "Extended."  Once I was able to establish this API, I thought it would be fairly straightforward for the rest of the development team to move forward.

I thought incorrectly.

As .NET developers, I think we're conditioned from the time that we open the IDE to make sure that event handlers are wired up throughout the lifetime of the application.  In fact, both C# and Visual Basic make it so easy for multiple methods to handle events, that it's sometimes silly not to.  C# and Visual Basic event handling syntax is syntactical sugar of the Observer pattern.  And why shouldn't it be?  For probably 99.9% of the applications out there, it's great.

Still, the current project has me a bit miffed.

Consider that there are two instances in which the arm needs to be extended: one to accept the user's item, and the other to re-dispense it.  Dispensing the item happens automatically when the arm is flipped upside-down and then extended.  So, I can track state:

private void Arm_Extended(object sender, EventArgs e)
{
    if (receivingItem)
    {
        // wait for button press
    }
    else // if dispensing item
    {
        Arm.Retract();
    }
}

Doesn't this seem kludgy to you?  If not here, then consider that within a single class I potentially have six objects reporting asynchronous task results that may need to be handled differently depending on the state of the machine.

Unfortunately, the alternative method seems just as kludgy:

private void ArmExtendedForUserPrompt(object sender, EventArgs e)
{
    Arm.Extended -= handlerForArmExtendingForPrompt;
    Controller.PromptUserForItem();
}

private void ArmExtendedForDispensing(object sender, EventArgs e)
{
    Arm.Retracted += handlerForArmRetractAfterDispenseCompleted;
    Arm.Extended -= handlerForArmExtendedForDispensing;
    Arm.Retract();
}

The primary reason I've chosen the latter approach is that stack traces have a bit more meaning to me.  That's it.  I guess it's arguable that I don't need to manage umpteen state flags.  ( As a side note, I've just learned that the spell checker in Windows Live Writer considers "umpteen" to not be a spelling error ).  But the truth is that, state flags or function pointers, I'm still managing state.

It might have been more appropriate to handle asynchronous callbacks as parameters to functions:

public void Extend(object state, AsyncCallback callback) { ...

This is tricky, too; it means needing to manage an additional two variables per asynchronous call.  For an object that might support multiple concurrent asynchronous operations, that can become a nightmare of complexity management.

I don't have the right answer for this.  But it's definitely something to watch out for in the future.

Posted on Monday, April 21, 2008 10:43 PM | Back to top


Comments on this post: The Difficulties of Using a Multicast Event-based API

# re: The Difficulties of Using a Multicast Event-based API
Requesting Gravatar...
I've been running into this myself where I can't determine a better way to handle state without making it semi-kludgy.

In my project, I've been doing Asynchronous WCF calls from silverlight pages. But I decided to let the silverlight pages/controls execute EventArgs through a command service. This way, logging in from the login control looks like:

LoginEventArgs e = new LoginEventArgs();
e.UserName = UserNameTextBox.Text;
e.Password = PasswordTextBox.Text;
MyServices.Current.Navigation.Execute<LoginEventArgs>("/service/user", e);

The actual class that implements the ICommand simply takes the generic event args type and sees what route it needs to take with the web service. So, in the case of LoginEventArgs it calls the web service's login method.

Since it's asynchronous though I went the same route only from the other end. So I have a different class that implements another ICommand that handles ui event args. At the same time I have service watchers that simple wire to the web service's events and trigger the ui event args like so:

// wire to callbacks
service.LoginCompleted += new EventHandler<LoginCompletedEventArgs>(login_Completed);

void login_Completed(object sender, LoginCompletedEventArgs e) {
MyServices.Current.Navigation.Execute<LoginCompletedEventArgs>("/ui/user", e);

Back in the UI area, I have a command that simple takes the event args, sees what type it is and updates UI accordingly.


-- That was a really long comment, I know. But it's been slightly confusing/weird coding all this up.
}
Left by Thomas Holloway on Jun 05, 2008 4:39 PM

# re: The Difficulties of Using a Multicast Event-based API
Requesting Gravatar...
Actually, depending on the context of your application, the second method is going to get you into trouble. Specifically, in what order do you switch event handlers? If you remove the old one first and then add the new one, then there is a brief period of time when there is no handler at all. If you add the new one first and then remove the old one, there is a period of time when both handlers may be invoked.

Generally speaking, I have found that synchronized state flags are the only reliable way to handle these issues.
Left by David Nelson on Jun 26, 2008 12:44 PM

Your comment:
 (will show your gravatar)


Copyright © Robert Paveza | Powered by: GeeksWithBlogs.net