C# поток спит на событие 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 миллисекунд "привет твоему другу".

Я так много слышал, не используйте сон на вашем коде..

Какой недостаток здесь, чтобы использовать сон? Если в последовательный порт поступит больше данных, новое событие войдет в dataReciver, потому что оно будет открыто во втором потоке.

так в чем же недостаток и как лучше / лучше всего реализовать это без сна?

1 ответ

Я использую блокировку, потому что я хочу только 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");
    }
}

Я упустил такие тонкости, как обработка исключений и более надежная обработка задач. Но вышеизложенное является основной идеей. Обратите внимание, что весь прием выполняется в одном цикле, без необходимости синхронизации между потоками.

Другие вопросы по тегам