1

I'm trying to determine the best way to approach this problem I am having with queuing outgoing messages to several COM ports. Each message is sent to the transmission queue of a static class that interfaces with multiple serial devices (Facade pattern). Each message is de-queued by a thread that is started upon the first established connection.

These messages can either request data from the serial device or simply write to an internal register. Either way, the handled message needs to relay back to the caller who originally submitted the message to the queue, the result of the IO operation (in order to process incoming data & update the UI).

So far I have attempted using three separate patterns, all of which I'm not sure the most appropriate.

1. Multiple listeners subscribed to events fired upon IO operation completion.

No queue involved. Callers simply invoke synchronous methods directly on the static class.

    public void InstrumentCommandComplete(string aHwid, ResponseParameter aParameter, bool aConnState, object aResult)
    {
        OnInstrumentResponse?.Invoke(this, new InstrumentResponseArgs(aHwid, aParameter, aConnState, aResult));
    }

This will fire each time a IO operation has completed and pass any relevant received data. Any interested classes simply subscribed to this event and handle any cross-thread operations accordingly.

I have found this method the easiest to implement and in my case, is the most readable. However, as the serial management class abstracts access to several devices, this requires multiple lock() objects to avoid concurrent access to one port.

2. Command pattern with callbacks.

    public interface ICommand
    {
        void Execute();
    }

    class ConnectCommand : ICommand
    {
        private readonly Func<bool, int> callback;

        public ConnectCommand(Func<bool, int> aCallBack)
        {
            callback = aCallBack;
        }

        public void Execute()
        {
            callback(instrument.Connect());
        }
    }

In this case, commands are submitted to a queue in a static "CommandManager" and sequentially de-queued, processed and the caller informed via a provided callback delegate.

The issue here is that the callback method is a little more convoluted than my first attempt, as received data mostly consists of simple 16-bit integers.

3. Completion ports with callbacks.

Providing Asynchronous Serial Port Communication

Per the above question, I had attempted to implement Completion Ports. However I found that I required multiple AutoResetEvents to handle the many callbacks that from the static serial manager class.

I did not have much success with this method and abandoned shortly after beginning refactoring as I needed to many signal variables to emulate synchronous calls to the ports.


I'm just having difficulty with finding the best implementation to handle requests to the device. At this point it seems most appropriate to:

a) either spawn new BackgroundWorkers for each request or...

b) submit each request to a ConcurrentQueue where each request contains a callback and is sequentially de-queued by a 'Manager'.

If anyone had thoughts on any alternate implementations, I would love to hear them.

Community
  • 1
  • 1
wubzorz
  • 57
  • 6
  • Hard to guess how this went wrong. There must be only **one** AutoResetEvent since a serial device can handle only one command at a time. You reset it when you send the command and set it when the response is received. And you need an outer lock so only one thread can use that ARE. Thus also automatically ensuring that only one command can be sent at the same time. If you use a Task to do this then you automagically get the async/await support. – Hans Passant Sep 08 '16 at 14:46
  • Hi Hans, thank you for your reply. My first method does something similar to what you are describing. Each call to a serial device is spawned in a BackgroundWorker and waits for any locks on the object to free. My issue is that some calls to the device are blocking (although the majority operate asynchronously). I'm just having difficulty with finding the best implementation to handle requests to the device (at this point it seems a) either spawning new BackgroundWorkers for each request or b) submitting each request to a ConcurrentQueue where each request contains a callback). – wubzorz Sep 08 '16 at 22:29

0 Answers0