【发布时间】:2016-09-30 10:59:50
【问题描述】:
我正在编写一个程序,它从串行端口读取每秒数据并将其保存在文本文件中/在 GUI 上显示。阅读以单击按钮开始和结束。
我尝试了一些不同的计时器来解决这个问题,但每个计时器都会带来一些麻烦(见下文)。
我的试训:
serialPort1.ReadTimeout = 2000;
System.Timers.Timer:
private void timer1_Tick(object sender, EventArgs e)
{
if (!serialPort1.isOpen)
{
serialPort1.Open();
}
serialPort1.WriteLine("INFO"); //Send data command
string data = serialPort1.ReadLine();
serialPort.Close();
editData(data); //Method for GUI update and textfile log
}
可以使用 timer1.Start() 和 timer1.Stop() 轻松启动和停止。问题是,System.Timers.Timer 在 GUI Thrard 上运行并在调用 serialPort.read 和 serialPort.Close() 时冻结 GUI。
后台工作人员:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while (backgroundWorker1.CancellationPending == false)
{
if (!serialPort1.isOpen)
{
serialPort1.Open();
}
serialPort1.WriteLine("INFO");
string data = serialPort1.ReadLine();
serialPort.Close();
Invoke((MethodInvoker)(() => editData(data)); //Method for GUI update and textfile log
}
}
异步运行。我需要每秒运行一次程序。
System.Timers.Timer 调用 Backgroundworker:
private void timer1_Tick(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (!serialPort1.isOpen)
{
serialPort1.Open();
}
serialPort1.WriteLine("INFO");
string data = serialPort1.ReadLine();
serialPort.Close();
Invoke((MethodInvoker)(() => editData(data)); //Method for GUI update and textfile log
}
在数据读取过程需要更长的时间或发生 serialPort.readTimeout 之前,这可以正常工作。 Backgroundworker 只能运行一次。所以我认为这不是一个选择。
System.Threading.Timers:
System.Threading.Timer timer;
timer = new System.Threading.Timer(_ => readSerialPort(), null, 0, 950);
private void readSerialPort()
{
if (!serialPort1.isOpen)
{
serialPort1.Open();
}
serialPort1.WriteLine("INFO");
string data = serialPort1.ReadLine();
serialPort.Close();
Invoke((MethodInvoker)(() => editData(data)); //Method for GUI update and textfile log
}
这很好,但问题是,我无法停止并重新开始阅读。
有人知道在这种情况下我应该使用哪个计时器吗?
【问题讨论】:
-
好吧,你已经概述了你的选择,并为每一个添加了推理。您到底期望什么作为答案? :)
-
System.Timers.Timer 默认不在 UI 线程上运行,只有在你设置了 SynchronizingObject 时才运行。
-
@Luaan 我正在寻找一个选项,我可以在其中启动和停止数据读取,并且在 serialPort.Close()、/SerialPort.ReadLine() 时 GUI 不应该冻结
-
另一种选择是不使用任何计时器,而是使用一个简单的后台线程来处理启动/停止并进行适当的循环以定期从端口读取。
-
您可以停止并重新启动
System.Threading.Timer- 只需使用Timer.Change()。因此,我建议您使用此计时器。
标签: c# multithreading timer