I’m looking to do both synchronous communication (over serial) using .NET’s SerialPort and also have asynchronous communication (over Ethernet) using .NET’s Socket.
The current implementation has a Connection class that declares both a SerialPort and Socket, and depending on what the user has defined the device’s connection type in the GUI–either COM or Ethernet–the Connection class will initialize the appropriate serial or socket port.
I have a ConnectionManager that holds all the Connections. So if the user creates a device using the same connection info, it doesn’t create a new Connection; instead, it is just assigned the Connection that is found in ConnectionManager.
This is a problem, because I need to do synchronous communications as well as asynchronous. What happens is there is a loop that creates Tasks while I’m connected to a device and each Task is trying to do a Send and Receive, and since it takes longer for the device to complete a task, than it takes the software to create tasks, there is a lot concurrency problems (blocked threads). Since I need to do synchronous communication, I lock a Mutex before my send Send and release the mutex after my Receive–to assure for every Send I get a Receive. This is not good because then when I would try to do Async communications it will be throttled due to the mutex.
So my question is what is the best design to follow when trying to handle asynchronous and synchronous communications at the same time? Should there be two different connection classes (AConnection, BConnection) that inherit a Connection interface with Send, Receive, Open, Close methods?
Any help is appreciated.
In general, you should alway prefer object composition over class inheritance. What that means is, instead of creating a super-class (say
WorkClass) with most of the functionality that you need and then two concrete sub-classes that inherit from it (sayAWorkClass : WorkClassandBWorkClass : WorkClass) and use/override those functions, you should crease two concrese classes with no inheritance (AClassandBClass) which “have a”WorkClassas a member variable.Taking this a bit further, and ultimatley trying to answer your question, it sounds like you want to implement the Strategy Pattern which will allow you to switch “strategies” (like between sync and async communication) very easily and allows you to add new “strategies” down the line without much effort (or make modifications to existing ones without having to worry about ripple-effects as much).
Here is a sample Strategy implemented in C#:
To tie this in with the first paragraph, then use WorkClass like this:
You can see that the user of your
WorkClass(which isMyWorkContextin this case) doesn’t know anything about your strategies, nor should it. It just tells the worker enough for it to know what to do, and then the worker knows which strategy it needs to use to do it. The strategies themselves are the only ones that know how the work is actually done, which is really nice for testing and maintenance.