我有一个.NET CORE 2.1控制台应用程序,它通过2个comPort(rs232)与两个half-duplex
的设备进行通信。
两个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
。
答案 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");
}
}
根据我的测试,问题已经解决。