2015-07-21 46 views
0

我正在尝试编写一个代表与设备通过RS232连接进行通信的类。这个设备可以被读取和写入,这可以由多个线程完成。使用多线程使用的RS232?

到目前为止,我选择将该类设置为单例类,因为它有意义,只有一个连接到设备应该永远存在。我还实施了两个接口IDataProviderIDataConsumer。这些只是定义了方法Boolean ReadData(out Object readData, params Object[] args)WriteData(Object inData, params Object[] args)。随着界面我也写了RS232Device。这实现了将端口Open(),Close(),Read()Write()的方法。

以下是我的课程概述。

public class DeviceIO : RS232Device, IDataProvider, IDataConsumer 
{ 
    public static DeviceIO Instance { get { return lazyInstance.Value; } } 
    private static readonly Lazy<DeviceIO> lazyInstance 
     = new Lazy<DeviceIO>(() => new DeviceIO()); 

    private DeviceIO() : base() {} 

    public void ConfigurePort(SerialPortConfig inConfig) 
    { 
     Configure(inConfig); 
    } 

    public Boolean ReadData(out Object readData, params Object[] args) 
    { 
     readData = null; 
     return false; 
    } 

    public Boolean WriteData(Object inData, params Object[] args) 
    { 
     return false; 
    } 
} 

我现在的问题是我如何使这个线程安全。我会假设在ReadDataWriteData之内,我会锁定Object的某个实例。这就是我需要做的一切吗?基本上就像下面的修改一样?

我可以将下面的Instance分配给各种线程,并且在两个线程可能尝试同时写入设备时没有任何问题吗?

public class DeviceIO : RS232Device, IDataProvider, IDataConsumer 
{ 
    public static DeviceIO Instance { get { return lazyInstance.Value; } } 
    private static readonly Lazy<DeviceIO> lazyInstance 
     = new Lazy<DeviceIO>(() => new DeviceIO()); 

    private static readonly Object Schlage = new Object(); 

    private DeviceIO() : base() {} 

    public void ConfigurePort(SerialPortConfig inConfig) 
    { 
     lock(Schlage) 
     { 
      Configure(inConfig); 
     } 
    } 

    public Boolean ReadData(out Object readData, params Object[] args) 
    { 
     lock (Schlage) 
     { 
      readData = null; 
      return false; 
     } 
    } 

    public Boolean WriteData(Object inData, params Object[] args) 
    { 
     lock (Schlage) 
     { 
      return false; 
     } 
    } 
} 
+0

这是正确的。注意:你的'Schlage'变量不一定是'static'。 –

+0

还有一个问题,大多数情况下,当你试图查询串口设备时,你首先向RS232写入数据,然后读取一行数据。如果我输入'ReadData'方法并获得一个锁,我可以调用'WriteData'而不是自己死锁吗? – KDecker

+0

一旦锁定建立,'lock'只会阻止** OTHER **线程进入。从**相同的**线程内,从ReadData()到WriteData()不会阻塞,并且不会导致问题。 –

回答

1

我建议通过实现消息队列模式来更好地服务这种类型的场景。在这里,任何需要使用RS232设备的代码都会将请求排入队列,然后等待回复或反应。同时,恰好一个线程将服务于该队列的业务端,一次一个地从队列中取出队列,通过从RS232端口发送和/或接收信息来执行它,然后继续下一个排队的消息。

这有助于简化代码流,并有助于防止死锁。所有实际访问RS232资源的代码都只在一个线程上执行(您的队列服务线程)。至于其他所有线程,他们只需将他们的请求发送到队列 - 一个非常快速的操作,然后检查他们的响应。实现这个

一种方法是:

_myMessageQueue = new ConcurrentQueue<Rs232Message>(); 

到消息队列发布新的消息正是如此:

_myMessageQueue.Enqueue(message); 

和您检索排队的消息:

bool isOk = _myMessageQueue.TryDequeue(out message); 
+0

我喜欢这个想法,并最终找到了一种解决方案,有点类似于这个和我在OP中提出的建议。在过去的两年中,没有人想回答这个问题,你可以享用鸡肉晚餐。 – KDecker