c# - 从串口读取数据正在丢失包
问题描述
您好,我创建了一个从记分牌读取串行数据的程序,然后根据字符串,程序将数据分成表格上的不同框,然后分成不同的 txt 文件。这样做的目的是使用这些 txt 文件进行直播在篮球比赛中。这是我第一次使用串行数据,我不是一个很有经验的程序员。
我的问题,正如这篇文章的标题所暗示的那样,我时不时会无缘无故丢失一些包裹。这是随机发生的,例如在 10 秒内我可以 1 个包裹,而下一个没有或 4 个。
private void ReadData()
{
Thread MyThread = null;
{
try
{
ThreadStart ThreadMethod = new ThreadStart(ReadFromPort);
MyThread = new Thread(ThreadMethod);
}
catch (Exception e)
{
Console.WriteLine("Failed to create thread! " + e.Message);
return;
}
try
{
MyThread.Start();
}
catch (Exception e)
{
Console.WriteLine("The thread failed to start! " + e.Message);
}
}
}
//Recieves data and write them on textbox (optionally on a txt)
private void ReadFromPort()
{
while (Receiver == true)
{
try
{
int count = ComPort.BytesToRead;
System.Windows.Forms.Application.DoEvents();
byte[] data = new byte[count];
ComPort.Read(data, 0, data.Length);
currentMessage = Combine(currentMessage, data);
ReceivedData = (BitConverter.ToString(data));
if (count > 0)
{
if (chBoxUpdate.Checked)
{
DataType = count;
tempData = ReceivedData;
this.Invoke(new EventHandler(DisplayText));
if (chboxTxt.Checked)
{
this.Invoke(new EventHandler(ExportData));
}
}
else if (chBoxPrevious.Checked)
{
DataType = count;
tempData = ReceivedData;
this.Invoke(new EventHandler(ClearData));
this.Invoke(new EventHandler(DisplayText));
if (chboxTxt.Checked)
{
this.Invoke(new EventHandler(ExportData));
}
}
}
}
catch (Exception e)
{
}
}
}
//Displays Text
private void DisplayText(object sender, EventArgs e)
{
string temp;
Console.WriteLine(tempData+ " (" + tempData.Length.ToString() + ")");
try
{
if (tempData.Length == 38)// && ReceivedData.Substring(12, 5) == "03-02")
{
if (tempData.Substring(12, 5) == "03-02")
{
DataText.AppendText(tempData.Substring(24, 8));
DataText.AppendText("\n");
Blink.Text = "Reading...";
timer1.Start();
timer1.Enabled = true;
}
}
else
if (tempData.Length == 35)
{
if (tempData.Substring(12, 5) == "45-02")
{
AttackTime.AppendText(tempData.Substring(24, 5));
Blink.Text = "Reading...";
AttackTime.AppendText("\n");
timer1.Start();
timer1.Enabled = true;
}
}
else
if (tempData.Length == 29)
{
if (tempData.Substring(12, 5) == "03-36")
{
HomeScore.AppendText(tempData.Substring(21, 2));
Blink.Text = "Reading...";
HomeScore.AppendText("\n");
timer1.Start();
timer1.Enabled = true;
}
else
if (tempData.Substring(12, 5) == "03-46")
{
AwayScore.AppendText(tempData.Substring(21, 2));
Blink.Text = "Reading...";
AwayScore.AppendText("\n");
timer1.Start();
timer1.Enabled = true;
}
}
}
catch (ArgumentOutOfRangeException)
{
}
}
请记住,这里的 tempData 和 ReceivedData 是相同的,并且由于程序现在出现,没有任何特别的理由来设置 tempData=ReceivedData。这是我在开始时使用的不同的旧代码的一部分,我从未更改过,但它没有不影响程序。
起初我使用一个线程来启用 ReadFromPort 然后如果程序发现有可用数据在线显示它们并使用 DisplayText 并使用 ExportData 将数据导出到 txt。我认为问题出在某个地方但是因为我不是很有经验,所以我不知道在哪里。
关于如何改进我的代码有什么建议吗?如果您提供更多详细信息或信息,我可以提供。
解决方案
您正在使用Invoke
,这会阻塞调用者线程,直到事件被处理,并且由于您正在更新 UI,这可能需要一些时间。这可能会导致一些缓冲区溢出和数据被丢弃。所以你应该在阅读线程上做尽可能少的工作。
有几种选择
- 将数据放在concurrentQueue中,并让 UI 线程有一个计时器,该计时器会定期触发从队列中读取并更新 UI 的方法。
- 将数据放在concurrentQueue上,包装在阻塞集合中,让另一个后台线程使用GetConsumingEnumerable遍历阻塞集合,并在完成后将结果发布到主线程。如果要进行大量处理,这将是合适的。
- 使用BeginInvoke将接收到的数据发布到主线程,这不会等待调用完成,但可能会比以前的替代方案具有稍高的开销。我建议不要从后台线程访问任何 UI 属性,因为默认情况下,UI 类的任何属性都不是线程安全的。如果你只是阅读,即使你可能侥幸逃脱,我也不会冒险。
推荐阅读
- python - 如何根据 Jupyter 中的现有列在数据框中创建新列?
- vue.js - vuetify 数据表,以及来自 json 对象的绑定数据
- batch-file - For循环递归地创建丢失的文件夹
- c# - C#在继续之前等待异步方法完成
- c++ - 带有子通道依赖项的布局转换不起作用
- android - 在多个模拟器上运行 Flutter 应用程序
- python - 在 Python 中使用 cv.goodFeaturesToTrack 的图像直线部分的角
- python - 直方图相关特定列
- c# - 如何访问“系统卷信息”目录中的文件
- python - 上升超过运行斜率计算器,输出到英尺和英寸