.NET CORE(在Windows上),DataReceived称为一个串行端口的频率,该频率受其他串行端口的影响

时间:2018-11-27 20:38:56

标签: c# .net performance

我有一个.NET CORE 2.1控制台应用程序,它通过2个comPort(rs232)与两个half-duplex的设备进行通信。

  • COM1上的设备A,波特率9600,我的应用程序每200毫秒轮询一次,并在50毫秒内获得响应。
  • COM2上的设备B,波特率1200,我的应用程序每400毫秒接收一次轮询,并在50毫秒内响应它。

两个comPort的代码完全分开,没有共享变量,没有引用等。

对于设备A:

private ConcurrentQueue<object> outgoingMessageQueue = new ConcurrentQueue<object>();
this.comPort1.DataReceived += (a,b)=>{
    while (this.comPort1.BytesToRead > 0){
        var b = this.comPort.ReadByte();
        buffer.Add((byte)b);
    };
    if(CheckIsFullMessage(buffer))
    {//fire event for consume}

};
ThreadPool.QueueWorkerThread((_)=>{
while(true){
    Thread.Sleep(200); 
    if (this.outgoingMessageQueue.TryDequeue(out object pendingForWrite))
    {this.comPort1.Write(pendingForWrite); }
    else
        this.comPort1.Write(new PollMsg());
}};
//business logic, queue a request at any time.
this.outgoingMessageQueue.Add(new requestMessage()); 

对于设备B:

this.comPort2.DataReceived += (a,b)=>{
    while (this.comPort2.BytesToRead > 0){
        var b = this.comPort.ReadByte();
        buffer.Add((byte)b);
    };
    if(CheckIsFullMessage(buffer))
    {
      //trigger business logic, consume the buffer and construct a response.
      //this.comPort2.Write(response,0,response.length); 
    }       
};

我注意到一件事,如果我打开设备B,则设备A (comPort1)的DataReceived将被随机延迟调用( (从毫秒到秒),在延迟期间,设备A的200毫秒轮询从未停止,因此我会突然从DataReceived处从设备A获得大量数据。

谁能帮忙,为什么这两个通信相互影响?

-----更多测试----

我进行了一项测试,将3个comPort中的3个设备A连接到应用中,它们运行良好,没有延迟DataReceived

1 个答案:

答案 0 :(得分:0)

经过一些测试和从Web发布后,我在.NET CORE上确认了此行为,多次SerialPort的写入和接收可能会延迟DataReceived的触发,因此,我没有等待,而是添加了一个代码以主动拉动

    public void Start()
    {
        this.comPort.DataReceived += (_,__)=>{this.PullPortDataBuffer();};
        //for very fast time accurate call(my app send&receive data every 200ms), use dedicated thread rather than timer.
        this.pullingSerialPortBufferLoop = new Thread(() =>
        {
            while (true)
            {                
                Thread.Sleep(200);
                this.PullPortDataBuffer();
            }
        });
        this.pullingSerialPortBufferLoop.Start();
    };
    var buffer = new List<byte>();
    private void PullPortDataBuffer()
    {
        if (0 == Interlocked.CompareExchange(ref this.onPullingComPortBuffer, 1, 0))
            try
            {

                while (this.comPort.BytesToRead > 0)
                {                        
                    this.buffer.Add((byte)b);
                }

                this.ConsumeBufferIfFull(this.buffer);
            }
            catch (Exception ex)
            {}
            finally
            {
                this.onPullingComPortBuffer = 0;
            }
        else
        {
            if (logger.IsDebugEnabled)
                logger.Debug(this.comPort.PortName + " concurrent enter Port_DataReceived");
        }
    }

根据我的测试,问题已经解决。