Sharing a single resource (serial port) between multiple applications
I need some architectural guidance. Here's my objective.
I have a piece of robotic hardware that performs multiple functions (i.e. it has several distinct logical devices). For the sake of illustration, let's say it is a robot arm with interchangeable attachments. The hardware has a single serial port that it uses to connect to a PC开发者_StackOverflow中文版, so that it can be controlled by various different applications. The arm itself and the interchangeable attachments are addressable over the single serial port.
I need to provide a service, the exposes several interfaces. The interfaces might be called something like:
IRobotArm
IGrabberAttachment IDrillAttachment
and so on. Now, here's the tricky part. Each interface needs to be accessed by completely different, isolated applications. So the robot arm and the grabber attachment might be controlled by completely different applications, simultaneously - or they might be controlled by the same application.
So that's my architectural puzzle. How do I provide multiple interfaces to multiple client applications, while ensuring only one instance of the serial port is created and that commands can be correctly serialized, etc.
One more additional requirement: I'll be working in .NET/C# but the client applications may well expect to use a COM interface, so the solution needs to work with COM Interop.
Ideas please!
You need one controller process that actually opens the serial port and sends/receives data.
Your DLLs exposing those interfaces should communicate with the controller process, not the serial port directly.
If your controller process (the part that opens/closes port and does transmit and receive) is accessible by several applications simultaneously you are going to need to put some synchronization mechanisms in place, otherwise two applications could attempt to send a message simultaneously, which could cause problems parsing the response from the robot arms.
Assuming you have a single controller process or service running, you could just use the C# lock keyword, like shown below (assuming a simple ASCII type protocol)
This only works if the controller is in its own process, the "lock" keyword will not work cross process. Also don't forget to Dispose of the SerialPort class when you shut down.
Object _access = new Object();
SerialPort _port;
public void Open()
{
lock( _port )
{
if( _port == null )
{
_port = new SerialPort("COM1", 9600, Parity.None, 8,StopBits.One );
_port.Open();
_port.NewLine = "\r";
}
}
}
public void Close()
{
// TBD
}
public string SendAndRecieve( string cmd )
{
String response;
lock( _access )
{
// Assume port is already opened
_port.WriteLine(cmd);
response = _port.ReadLine();
}
return response;
}
精彩评论