【发布时间】:2009-08-05 15:20:23
【问题描述】:
我有一段丑陋的串口代码,非常不稳定。
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(100);
while (port.BytesToRead > 0)
{
var count = port.BytesToRead;
byte[] buffer = new byte[count];
var read = port.Read(buffer, 0, count);
if (DataEncapsulator != null)
buffer = DataEncapsulator.UnWrap(buffer);
var response = dataCollector.Collect(buffer);
if (response != null)
{
this.OnDataReceived(response);
}
Thread.Sleep(100);
}
}
如果我删除任何一个 Thread.Sleep(100) 调用,代码将停止工作。
当然,这确实会减慢速度,如果大量数据流入, 除非我让睡眠变得更大,否则它也会停止工作。 (像纯粹的死锁一样停止工作)
请注意 DataEncapsulator 和 DataCollector 是组件 由MEF提供,但它们的性能相当不错。
该类有一个 Listen() 方法,该方法启动一个后台工作者 接收数据。
public void Listen(IDataCollector dataCollector)
{
this.dataCollector = dataCollector;
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
port = new SerialPort();
//Event handlers
port.ReceivedBytesThreshold = 15;
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
..... remainder of code ...
欢迎提出建议!
更新: *只是简要说明 IDataCollector 类的作用。 无法知道是否已发送数据的所有字节 在单个读取操作中读取。所以每次读取数据时 传递给 DataCollector,它在完成时返回 true 并且 已收到有效的协议消息。在这种情况下,它只是 检查同步字节、长度、CRC 和尾字节。真正的工作 稍后由其他类完成。 *
更新 2: 我现在按照建议替换了代码,但仍然有问题:
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var count = port.BytesToRead;
byte[] buffer = new byte[count];
var read = port.Read(buffer, 0, count);
if (DataEncapsulator != null)
buffer = DataEncapsulator.UnWrap(buffer);
var response = dataCollector.Collect(buffer);
if (response != null)
{
this.OnDataReceived(response);
}
}
您会发现,这在连接快速稳定的情况下效果很好。 但是每次接收到数据时都不会调用 OnDataReceived。 (有关更多信息,请参阅 MSDN 文档)。所以如果数据变得碎片化 并且您只在事件数据丢失时读取一次。
现在我记得为什么我首先要有循环,因为 如果连接速度慢或不稳定,它实际上必须读取多次。
显然我无法回到while循环解决方案,那我该怎么办?
【问题讨论】:
-
把它拖到棚子后面开枪! ;-)
标签: c# .net performance serial-port