@TomWr 你说得对,从我所读的来看确实是这样。
以下是你的代码片段和我的评论:
try
{
btr = serialPort1.BytesToRead;
if (btr > 0)
Thread.Sleep(300);
btr = serialPort1.BytesToRead;
if (btr > 0)
{
Thread.Sleep(300);
btr = serialPort1.BytesToRead;
numbytes = serialPort1.Read(stuffchar, 0, btr);
for (x = 0; x < (numbytes); x++)
{
cc = (stuffchar[x]);
stuff += Convert.ToString(Convert.ToChar((stuffchar[x])));
}
我猜想和idstam上面提到的一样,可能是为了检查设备是否发送了数据并获取它们。
您可以使用适当的SerialPort方法轻松地重构此代码,因为实际上有更好和更简洁的方法来检查串口上是否有可用的数据。
与其像这样“我正在检查端口上有多少字节,如果有什么东西,那么我等待300毫秒,然后再次进行相同的操作。”结果可怜,最终会变成:
“是的,2次300毫秒= 600毫秒,或者只有一次(取决于是否已经第一次),或者根本没有(取决于您通过此UI与之通信的设备,它可以非常懒惰,因为Thread.Sleep阻止了UI ...)。"
首先,让我们考虑一下,如果您尝试保持尽可能相同的代码库,为什么不等待600ms呢?
或者,为什么不直接使用ReadTimeout属性并捕获超时异常,虽然这不太干净,但至少在可读性方面更好,而且您直接获取了String而不是使用Convert.ToChar()调用...
我感觉这段代码已经从C或C++移植过来了(或者至少是背后的原理),来自一个更多地拥有嵌入式软件背景的人。
无论如何,回到可用字节检查的数量上,我的意思是除非在另一个线程/BackgroundWorker/Task处理程序中刷新串行端口数据,否则我不认为需要检查两次,特别是按照编码方式。让它更快?并不是真的,因为如果串行端口上实际上有数据,会有额外的延迟。这对我来说并没有太多意义。
使您的片段稍微改进的另一种方法是使用ReadExisting()进行轮询。
否则,您还可以考虑使用SerialPort BaseStream的异步方法。
总之,在没有访问其余代码库(即上下文)的情况下很难说。
如果您有关于目标/协议的更多信息,可能会给出一些关于要做什么的提示。否则,我只能说这似乎编码很差,再次超出了上下文。
我反复三思汉斯提到的UI响应能力,我真的希望您的片段正在运行一个不是UI的线程中(尽管您在帖子中提到UI正在轮询,但我仍然希望该片段是针对另一个工人的)。
如果这确实是UI线程,那么每次调用Thread.Sleep都会阻塞它,使得UI对用户的交互不太响应,可能会让最终用户感到沮丧。
还值得订阅DataReceived事件,并使用处理程序执行所需操作(例如,使用缓冲区和比较值等)。
请注意,mono仍未实现此事件的触发,但如果您正在运行纯MS .NET实现,则没有多线程的麻烦,这是完全可以接受的。
简而言之:
- 检查哪个线程负责您的代码片段,并注意UI的响应性。
- 如果是UI,请使用另一个线程通过Thread、BackgroundWorker(Threadpool)或Task来处理它。
- 使用异步流方法,以避免UI线程同步的麻烦
- 尝试看看目标是否真的值得使用两个300毫秒的Thread Sleep方法调用
- 您可以直接获取String,而不是自己收集Bytes(如果所选编码能够满足您的需求)。