使用多线程使用的RS232?

时间:2015-07-21 18:11:07

标签: c# multithreading

我正在尝试编写一个代表通过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;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

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

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

实现这一目标的一种方法是:

_myMessageQueue = new ConcurrentQueue<Rs232Message>();

将新消息发布到您的消息队列:

_myMessageQueue.Enqueue( message );

并使用以下命令检索排队的消息:

bool isOk = _myMessageQueue.TryDequeue( out message );