我应该使用哪个定时器

本文关键字:定时器 我应该 | 更新日期: 2023-09-27 18:09:51

我正在编写一个程序,从serialPort读取每秒钟的数据,并将其保存在文本文件中/显示在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 . timer . timer运行在GUI线程上,并且在serialPort时冻结GUI。read和serialPort.Close()被调用。


Backgroundworker:

    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
        }
    }  

asynchronlly运行。我需要每秒钟运行一次程序。


System.Timers。

    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发生。后台工作者只能运行一次。所以我认为这不是一个选择。


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.Threading.Timer

var timer = new System.Threading.Timer(cb, null, 1000, 1000); // init   
timer.Change(Timeout.Infinite, Timeout.Infinite); // stop   
timer.Change(0, 1000); // start

注:不要忘记处理定时器

您可以使用线程实现此逻辑。元代码如下:

        var stopEvent = new ManualResetEvent(false);
        var thread = new Thread(() => {
            if (!serialPort1.isOpen)
            {
                serialPort1.Open();
            }
            try
            {
                while (!stopEvent.WaitOne(0))
                {
                    try
                    {
                        serialPort1.WriteLine("INFO");
                        string data = serialPort1.ReadLine();
                        Invoke((MethodInvoker)(() => editData(data)));
                    }
                    catch (Exception)
                    {
                        // Handle exception, e.g. a reading timeout
                    }
                    stopEvent.WaitOne(1000); //Thread.Sleep(1000);
                }
            } finally
            {
                serialPort.Close();
            }

        });
        thread.Start();
        //call it to stop the loop.
        stopEvent.Set();
    }

可以实现更复杂的逻辑,如停止和恢复读取。只需使用更多事件。如果你不熟悉事件,你可以使用布尔变量,但是把它们定义为volatile