11

我有许多线程(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 ;  
4

3 回答 3

7

如果线程真的在等待类似于 WaitForSingleObject 的东西,它不使用处理器时间,然后超时,则没有理由在线程中延迟睡眠。

您的用户没有等待线程响应,它没有使用处理器时间,并且其他线程不会被阻塞,因此没有理由让线程进入睡眠状态。

正如 David Heffernan 在他的评论中指出的那样,如果它现在没有使用 100% 的 CPU,那么就没有问题。

如果您是单线程的,您可能会使用 sleep(),并且您必须偶尔在等待串行端口响应之间响应用户。

此外,让线程休眠不会提高效率。它只会将处理器周期让给其他线程。

看看sleep(0)线程中“浪费时间”的 CPU 高效方式。

于 2011-11-01T19:41:18.383 回答
2

防止线程使用 CPU 时间的最有效方法是将其置于“等待模式”。

我根本不使用delphi,但似乎基本原理就在那里。请参阅“第 11 章。同步器和事件”,更具体地说,“使用信号量进行事件模拟”

如果您想在不使用 CPU 的情况下等待,请使用WaitForEvent

检查事件的信号状态。如果它指示事件已发出信号,则内部信号量发出信号,并且在信号量上阻塞的线程计数递减。然后阻塞线程的计数增加,并在内部信号量上执行等待。

如果这与 I/O 相关,那么事情会有所不同。如果它是一个套接字,那么它可能已经阻塞,如果它是异步 I/O,那么你可以使用信号量WaitForEvent等等。

在 .NET 中有Monitor.Wait, Monitor.Signal, ManualResetEvent,CountDownLatch等,但我不知道 delphi 中的等价物是什么。

于 2011-11-01T19:44:52.713 回答
2

我不能说 AsyncFree 的功能,但一般来说,Windows 中的 COM 端口编程支持重叠 I/O,因此您可以通过使用该WaitCommEvent()函数与一系列函数之一有效地等待数据到达时的通知WaitFor...(),例如WaitForSingleObject(). 线程可以进入睡眠状态,直到发出通知,此时它“唤醒”从端口读取,直到没有进一步的读取,然后它可以回到睡眠状态,直到下一次通知。

于 2011-11-02T01:41:12.267 回答