我在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毫秒后回答的序列号#34;你好朋友"。
我听到这么多,不要在你的代码上使用睡眠......
这里使用睡眠的缺点是什么?如果有更多数据将在serialport上运行,那么新事件将进入dataReciver,因为它将在secondery线程上打开。
那么缺点是什么?没有睡眠的更好/最好的方法是什么?
答案 0 :(得分:2)
我使用锁,因为我只想在这个阅读中使用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");
}
}
我遗漏了异常处理和更强大的任务处理等细节。但以上是基本思路。请注意,所有接收都在单个循环中完成,无需跨线程同步。