【发布时间】:2019-04-29 16:06:09
【问题描述】:
我有一个 .NET CORE 2.1 控制台应用程序,它通过 2 个 comPort (rs232) 与 2 个都是 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 将被随机延迟调用(来自 ms到秒),在延迟期间,设备A的200ms轮询从未停止过,所以我会突然从设备A获得大量数据DataReceived。
谁能帮忙,为什么这两个 comPorts 会相互影响?
-----更多测试----
我做了一个测试,将 3 个 comPort 中的 3 个设备 A 连接到应用程序中,它们运行良好,没有 DataReceived 延迟。
【问题讨论】:
-
有可能,DataReceived 是在线程池线程上触发的。因此,如果您运行的设备过多,则可能需要一段时间才能对其进行维修。 Thread.Sleep() 和 while(true) 是在 tp 线程上的彻底实践,所以首先从那里开始,使用 Thread。
-
是的。研究调整
ReceivedBytesThreshold以潜在地限制事件频率。 Some success reported here。如果你用谷歌搜索DataReceived问题,这似乎是很多人的共同痛点。 -
我忘了说,“数据太多”是好事,不是坏事。保证迟早会发生。想想垃圾收集或非常繁忙的机器。所以它一定不是问题,首先解决它。您可能需要联系
//fire buffer full event。它没有满,几乎没有。只获得 1 或 2 个字节是正常的。强烈建议您进行缓冲,直到您获得设备的完整响应。 -
@HansPassant 1. 你建议像这样
new Thread(() => { while (true) Thread.Sleep(200);/* dequeue and send */ }).Start();,对吗?什么是我的好。 2.如果我将ThreadPool.SetMin(worker, io)设置为更高,是否有助于稳定onDataReceived? -
@NPras 设备 1 的完整消息长度从 3 到 14 不等,而设备 2 的长度为 4 到 15,并且似乎设置了
ReceivedBytesThreshold会降低呼叫频率,对吗?我的期望是增加频率。
标签: c# .net performance