0

我有一个运行 RS232 串行通信的 WPF 应用程序,我正在编写它来替换旧的(粗略写的)Borland C++ dos 可执行文件。

在我的应用程序中,为了将 UI 与通信分开,我在它自己的线程上运行串行。我每 30 毫秒向连接的设备发送消息。我已经设置了一个 SerialDataReceivedEventHandler 来捕获任何收到的消息。

    public override void DataRecieved()
    {
        _serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
    }

    public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
    {
        queue.Enqueue(((SerialPort)sender).ReadExisting());
    }

在接收到的处理程序中,我将接收到的消息排队,并在另一个线程中对它们执行我想要的操作。

我的问题是,当我在串行通信线路上放置示波器时,我看到我的大部分数据包都以 30 毫秒的间隔发出,但有些则以 40 毫秒的间隔发出。接收到的消息在 40ms 时与这些 out 消息不一致。

我使用 System.Timers.Timer 将我的时间间隔设置为 30 毫秒,并且只在 ElapsedEventHandler 上发送三个字节。

        // Initialize and Start timer
        timer = new Timer(30);
        timer.Elapsed += new ElapsedEventHandler(Timer_Elapsed);
        timer.Start();


    private void Timer_Elapsed(object source, ElapsedEventArgs e)
    {
        lock(lockObject)
        {
            // Write
            byte[] _buffer = { byte1};
            WriteBuffer(_buffer);


            // Write
            byte[] _buffer1 = { byte2 };
            WriteBuffer(_buffer1);


            // Write
            byte[] _buffer2 = { byte3};
            WriteBuffer(_buffer2);
        }
    }

System.Timers.Timer 中是否有一些东西会错过 30 毫秒的间隔并持续更长时间?我应该一起使用不同的计时器吗?

4

1 回答 1

0

我想到了。我将 StopWatch 与 Stopwatch.ElapsedMilliseconds 属性一起使用。当我的经过时间大于或等于 30 毫秒时,我会发送消息。

        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();

        while (!Stopped)
        {
            // Loop here. 
            // Received Event handler is capturing messages.

            // Wait 30ms between commands
            if (stopWatch.ElapsedMilliseconds >= 33)
            {
                lock (lockObject)
                {
                    // Write 
                    byte[] _buffer = { byte1, byte2, byte2 };
                    WriteBuffer(_buffer);
                }

                stopWatch.Reset();
                stopWatch.Start();
            }
        }

当我有计时器时

while (!Stopped)
{
     // Loop here. 
     // Received Event handler is capturing messages.
     // Timer is sending messages
}

这在 Timer 或延迟 (System.Threading.Thread.Sleep(30)) 上起作用的原因是我将线程放弃给 Windows 事件处理程序。这意味着我在等待 Windows 告诉我可以继续。我无法控制我的线程。

现在使用 StopWatch 并不完美,但它比 Timer 更接近,大约 32-33ms

谢谢 - @500 - 内部服务器错误,@Peter Ritchie 和我的同事

于 2013-08-16T17:57:05.283 回答