我有许多线程(100),每次执行几秒钟。当它们执行时,它们花费大量时间等待来自另一个系统(串行设备)的响应。我注意到一次执行100个线程可能是资源占用,所以我实际上限制了任何时候都可以启动的线程数。
虽然在线程中等待外部事件必须有好的和坏的方法,但我想到了这一点。这种方法是CPU密集型的吗?:
send command ;
repeat
until response arrived ;
process response ;
这种方法是否会提高效率?:
send command ;
repeat
Sleep (20) ;
until response arrived ;
process response ;
* 附加信息 *
环境是x86 Windows XP。线程代码是与串行设备进行的一系列长时间的交互,但通常,它包括将字符写入COM端口(使用AsyncFree串行库)并等待通过驻留在传入的字符缓冲区和他们到达时处理它们。我想这个串行库会让设备读写。线程中的时间可以长达一分钟,也可以短至几秒钟,但大部分时间都花在等待字符离开端口或等待响应字符(波特率很慢),因此我的问题是关于线程在等待时表现的最佳方式。目前我在打电话 Sleep
在一个循环中等待 CharactersInBuffer
变为非零,在到达时处理每个字符,并在我有完整的响应时退出该字符。所以代码看起来更像(忽略超时处理等):
send command ;
Packet = '' ;
repeat
repeat
Sleep (20) ;
until response character arrived ;
build Packet
until complete packet arrived
process response ;
如果线程真正等待WaitForSingleObject之类的东西,它不使用处理器时间,那么超时,就没有理由在线程中使用sleep来延迟。
您的用户没有等待线程响应,它没有使用处理器时间,并且其他线程不会被阻止,因此没有理由让线程进入休眠状态。
正如David Heffernan在评论中指出的那样,如果它现在没有使用100%的CPU,那么就没有问题了。
如果你是单线程的话,你可以使用sleep(),你不得不偶尔在等待串口响应用户之间做出响应。
此外,线程休眠不会使其更有效。它只会为其他线程产生处理器周期。
看一眼 sleep(0)
作为CPU在线程中“浪费时间”的有效方式。
防止线程使用CPU时间的最有效方法是将其置于“等待模式”。
我根本不使用delphi,但似乎基本原理就在那里。看到 “第11章同步器和事件” 更具体地说 “使用信号量的事件模拟”。
如果您想在不使用CPU的情况下等待,请使用 WaitForEvent
:
检查事件的信号状态。如果它指示事件已发出信号,则发信号通知内部信号量,并减少信号量上阻塞的线程数。然后递增阻塞线程的计数,并对内部信号量执行等待。
如果这与I / O相关,那么事情就会有所不同。如果它是一个套接字,那么它可能已经被阻塞,如果它是异步I / O,那么你可以使用一个信号量和 WaitForEvent
等等。
在.NET中有 Monitor.Wait
, Monitor.Signal
, ManualResetEvent
, CountDownLatch
等等,但我不知道delphi中的等价物是什么。
我不能说AsyncFree的功能,但一般来说,Windows中的COM端口编程支持重叠I / O,因此您可以通过使用以下方式有效地等待数据到达时的通知 WaitCommEvent()
功能与其中之一 WaitFor...()
一系列功能,如 WaitForSingleObject()
。线程可以进入休眠状态,直到通知发出,此时它“唤醒”从端口读取,直到没有任何进一步的读取,然后它可以回到睡眠直到下一次通知。