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");
}
}
Я упустил такие тонкости, как обработка исключений и более надежная обработка задач. Но вышеизложенное является основной идеей. Обратите внимание, что весь прием выполняется в одном цикле, без необходимости синхронизации между потоками.