c#thread在DataReceived事件上休眠

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c#thread在DataReceived事件上休眠相关的知识,希望对你有一定的参考价值。

我在c#上写了这段代码

public  class SerialClass 
{
    SerialPort s;
    public Serial()
    {
        InitSerialPort();
        s.DataReceived += dataReciver;

    }

    private void dataReciver(object sender, SerialDataReceivedEventArgs e)
    {
      lock (obj) 
    {
          while (s.BytesToRead >0)
           {
               var line = s.ReadLine();
               if(line=="hello")
               {
                   Thread.Sleep(500);
                   s.WriteLine("hello to you friend");
              }
              else  //......
        }       
           }
    }

}

当我从序列中得到“你好”时我想在500毫秒后回答“你好朋友”。

我听到这么多,不要在你的代码上使用睡眠..

这里使用睡眠的缺点是什么?如果有更多数据将在serialport上运行,那么新事件将进入dataReciver,因为它将在secondery线程上打开。

那么什么是缺点,什么是没有睡眠的更好/最好的方法来实现它?

答案

我使用锁是因为我想只有1个线程会在这个读数上

如果你做得对,你就不需要锁。

恕我直言,你应该完全避免DataReceived事件。在SerialPort.BaseStream中包装StreamReader,然后以异步方法循环读取。无论如何,我也不会将延迟,异步或其他方式与您的阅读顺序排列。你应该随时准备阅读。

你没有提供真正的代码,所以不可能提供真正的代码解决方案,但是这就是我如何编写你发布的代码:

public class Serial
{
    SerialPort s;

    public Serial()
    {
        InitSerialPort();

        // Ignore returned task...constructors shouldn't wait. You could store
        // the task in a class field, to provide a mechanism to observe the
        // receiving state.
        Task task = ReceiveLoopAsync();
    }

    private async Task ReceiveLoopAsync()
    {
        using (StreamWriter writer = new StreamWriter(s.BaseStream))
        using (StreamReader reader = new StreamReader(s.BaseStream))
        {
            string line;

            while ((line = reader.ReadLineAsync()) != null)
            {
                if (line == "hello")
                {
                    // Ignore returned task...we don't really care when it finishes
                    Task task = RespondAsync(writer);
                }
            }
        }
    }

    private async Task RespondAsync(StreamWriter writer)
    {
        await Task.Delay(500);
        writer.WriteLine("hello to you friend");
    }
}

我遗漏了异常处理和更强大的任务处理等细节。但以上是基本思路。请注意,所有接收都在单个循环中完成,无需跨线程同步。

以上是关于c#thread在DataReceived事件上休眠的主要内容,如果未能解决你的问题,请参考以下文章

serialport DataReceived事件

C# 线程问题,我无法正常工作,在 Events_DataReceived 中调用

C# Winform 串口问题

c# 定时器调用控件的事件处理事情出现卡死主界面如何解决

串口数据接收事件处理程序

winform串口控件serialPort1的使用