1. I/O operation example

Scenario: you're writing a software that tells file's size. A simple form with a textbox for the file's name, a button and a label to tells file's size.

Normally, you do:

private void btTellSize_Click(object sender, EventArgs args)
{
    lSize.Content = File.Length(tbFilename.Text);
}

Bad this is that this code may block UI thread. What if the file is actually on a network mapped drive?

With the MessagingBus you do:

private void btTellSize_Click(object sender, EventArgs args)
{
    long size;
    string name = tbFilename.Text;
    _Bus.PostMessageAsync(new SequentialMessage(
        new IOMessage(() => size = File.Lenght(name)),
        new UIMessage(() => lSize.Content = size)
    ));
}

This is much more complex. Good this is that UI doesn't get blocked. Bad thing is that you need to configure Bus and two subscribers to listen for IO and UI messages. As you'll see later, the latter isn't that hard.

2. CPU utilization

Scenario: you're writing a program for batch image resizing.

The logic is straightforward: Read image -> Resize -> Save image.

With MessagingBus, the algorithm looks like this:

 

Image img1, img2;
_Bus.PostMessageAsync(new SequentialMessage(
    new IOMessage(() => img1 = Load(Name)),
    new ComputeMessage(() => img2 = Resize(img1, args)),
    new IOMessage(() => img2.Save("resized " + Name))
));

The cute thing is: the subscriber for ComputeMessage is derived from GeneralMultiThreadedSubscriber and has the following lines:

 

 

public override int NumberOfWorkerThreads
{
    get { return Environment.ProcessorCount; }
}

Now, the code will keep both IO and CPU ultimately loaded for the task. Another thing: number of working threads is limited to amount of cores. You can place as many messages on the bus as you want, they will wait in queue to be processed by corresponding subscriber. This way the MessagingBus lib helps manage CPU time as a resource.

 

3. Controlling the time of IO execution

Scenario: the same app for telling file's size as in the first example.

Idea: user should see some feedback when I/O operation is taking long.

Code:

 

long size;
string name = tbFilename.Text;
_Bus.PostMessageAsync(
    new TimeCheckedMessage(
        new SequentialMessage(
            new IOMessage(() => size = File.Lenght(name)),
            new UIMessage(() => lSize.Content = size)
        ),
        TimeSpan.FromMilliseconds(400),
        new UIShowLongOperationMessage(),
        new UIHideLongOperationMessage()
        )
);

If the SequentialMessage takes less than 400ms to complete, everything's fine — user won't notice a thing. Otherwise, UIShowLongOperationMessage will be placed on the same bus. UI subscriber will get it and display a comprehensive "Please wait for I/O operation to complete...", keeping the rest of the UI responsive — user can resize the window, click other buttons and even change his mind of seeing the file's size at all.

4. Further beauty

Let the code speak for itself:

Bus.PostMessageAsync(new SequentialMessage(
    new ParallelMessage(
        new SequentialMessage(
            new ShowStatusMessage() { Status = "Loading Model..." },
            new ComputingLoadModelMessage()
            {
                Path = "FinalData",
                ModelConfiguration = ModelConfiguration
            },
            new ShowStatusMessage() { Status = "Model loaded." }
        ), 
        new ParallelMessage(LoadCharacterslist_msg.ToArray())
    ),
    new ConfigureModelMessage(),
    new PositionHandMessage()
    {
        BeforeExecution = (msg) => ((PositionHandMessage)msg).HandPosition = CachedMovements.First().Value.First()
    },
    new ShowStatusMessage()
    {
        Status = "Loading completed.",
        AfterExecution = (m) => Console.WriteLine("Loading completed.")
    },
    new EnableUIMessage(),
    new DirectUIActionMessage()
    {
        Action = delegate
        {
            SetCamera();
            DoubleAnimation animation = new DoubleAnimation(1.0, AnimationTS);
            this.btStartLearning.BeginAnimation(UIElement.OpacityProperty, animation);
        }
    }
));

The code describes a workflow of loading 3D model and associated data. It could be much cleaner thou. I love it anyway (maybe because I've created it).

5. Error handling

... to be continued ...

 

Last edited Sep 14, 2010 at 11:50 PM by modosansreves, version 2

Comments

No comments yet.