“浪费时间”最有效的 CPU 方式是什么?在一个线程中?
我有许多线程(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 ;
I have a number of threads (100's) that each execute for a few seconds at a time. When they are executing, they spend a significant amount of that time waiting for a response from another system (a serial device). I am mindful that having 100 threads executing at once could be a resource hog so I actually limit the number of threads that can start at any one time.
It occurs to me though that there must be good and bad ways of waiting for an external event inside a thread. Is this approach CPU-intensive?:
send command ;
repeat
until response arrived ;
process response ;
and does this approach make it more efficient?:
send command ;
repeat
Sleep (20) ;
until response arrived ;
process response ;
* ADDITIONAL INFO *
The environment is x86 Windows XP. The thread code is a long and involved series of interactions with a serial device but in general, it consists of writing characters to a COM port (using the AsyncFree serial library) and waiting for characters to be returned by camping on the incoming characters buffer and processing them when they arrive. I imagine the serial library makes device reads and writes. The time in the thread can be as long as a minute , or as short as a couple of seconds, but most of that time is spent waiting for characters to leave the port, or waiting for the response characters (baud rate is slow), hence my question about the best way for the thread to behave while it is waiting. Currently I am calling Sleep
in a loop waiting for CharactersInBuffer
to become non-zero, processing each character when it arrives, and exiting the thread when I have the complete response. So the code looks more like (ignoring handling of timeouts, etc):
send command ;
Packet = '' ;
repeat
repeat
Sleep (20) ;
until response character arrived ;
build Packet
until complete packet arrived
process response ;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果线程确实正在等待类似 WaitForSingleObject 之类的东西,它不使用处理器时间,然后超时,则没有理由通过睡眠来延迟线程。
您的用户不会等待线程响应,它不会使用处理器时间,并且其他线程不会被阻止,因此没有理由让线程休眠。
正如 David Heffernan 在他的评论中指出的那样,如果现在没有使用 100% 的 CPU,那么就没有问题。
如果您是单线程并且您必须偶尔在等待串行端口响应之间响应用户,则可以使用 sleep()。
此外,让线程休眠并不会提高效率。它只会将处理器周期让给其他线程。
看一下
sleep(0)
作为在线程中“浪费时间”的 CPU 有效方式。If the thread is truly waiting with something like a WaitForSingleObject, which uses no processor time, then times out, there is no reason to put a delay in the thread with sleep.
Your user isn't waiting on the thread to be responsive, it's not using processor time, and other threads won't be blocked, so there would be no reason to put the thread to sleep.
As David Heffernan indicated in his comment, if it's not using 100% of your CPU now, then there's no problem.
You might use sleep() if you were single threaded and you had to occasionally respond to the user in between waiting on the serial port to respond.
Also, having a thread sleep would not make it more efficient. It would simply yield processor cycles to other threads.
Take a look at
sleep(0)
as a CPU efficient way of "wasting time" in a thread.防止线程使用 CPU 时间的最有效方法是将其置于“等待模式”。
我根本不使用delphi,但似乎有其基础知识。请参阅“第 11 章. 同步器和事件” 以及更具体的<一个href="http://www.eonclash.com/Tutorials/Multithreading/MartinHarvey1.1/Ch11.html#Event%20simulation%20using%20semaphores。" rel="nofollow">“使用信号量进行事件模拟”。
如果你想等待而不使用CPU,那么使用
WaitForEvent
:如果这是与 I/O 相关的,那么事情会有点不同。如果是套接字,那么它可能已经处于阻塞状态,如果是异步 I/O,则可以使用信号量和
WaitForEvent
等。在.NET中有Monitor.Wait、Monitor.Signal、ManualResetEvent、CountDownLatch等,但是我不知道delphi中有哪些等效的东西。
The most efficient way to prevent a thread from using CPU time is to put it in a "wait mode."
I don't use delphi at all, but it seems that the fundamentals for that are there. See "Chapter 11. Synchronizers and Events" and more specifically "Event simulation using semaphores".
If you want to wait without using CPU, then use
WaitForEvent
:If this is I/O related, then things work a little different. If it's a socket, then it might already be blocking, if it's asynchronous I/O, then you can use a semaphore and
WaitForEvent
and so on.In .NET there is the
Monitor.Wait
,Monitor.Signal
,ManualResetEvent
,CountDownLatch
, etc., but I don't know what are the equivalent things in delphi.我无法评价 AsyncFree 的功能,但一般来说 Windows 中的 COM 端口编程支持重叠 I/O,因此您可以通过使用
WaitCommEvent()
函数和其中之一来有效地等待数据到达时的通知WaitFor...()
系列函数,例如WaitForSingleObject()
。线程可以进入睡眠状态,直到发出通知,此时它“醒来”以从端口读取数据,直到没有任何内容可读取,然后它可以返回睡眠状态,直到下一个通知。I cannot speak for AsyncFree's capabilities, but in general COM port programming in Windows supports Overlapped I/O, so you can efficiently wait for a notification when data arrives by using the
WaitCommEvent()
function with one of theWaitFor...()
family of functions, such asWaitForSingleObject()
. The thread can be put into a sleep state until the notify is issues, at which time it "wakes up" to read from the port until there is nothing further to read, then it can go back to sleep until the next notify.