C++ 我可以用什么来替换 Qt 应用程序中的 sleep 和 usleep?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1950160/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
what can I use to replace sleep and usleep in my Qt app?
提问by yan bellavance
I'm importing a portion of existing code into my Qt app and noticed a sleep function in there. I see that this type of function has no place in event programming. What should I do instead?
我正在将一部分现有代码导入我的 Qt 应用程序,并注意到其中有一个睡眠功能。我看到这种类型的函数在事件编程中没有立足之地。我应该怎么做?
UPDATE: After thought and feedback I would say the answer is: call sleep outside the GUI main thread only and if you need to wait in the GUI thread use processEvents() or an event loop, this will prevent the GUI from freezing.
更新:经过思考和反馈,我会说答案是:仅在 GUI 主线程之外调用 sleep,如果您需要在 GUI 线程中等待,请使用 processEvents() 或事件循环,这将防止 GUI 冻结。
采纳答案by yan bellavance
It is not necessary to break down the events at all. All I needed to do was to call QApplication::processEvents()
where sleep()
was and this prevents the GUI from freezing.
根本没有必要分解事件。我需要做的就是调用QApplication::processEvents()
where sleep()
was ,这可以防止 GUI 冻结。
回答by Rob
It isn't pretty but I found this in the Qt mailing list archives:
它并不漂亮,但我在Qt 邮件列表档案中找到了这个:
The sleep method of QThread is protected, but you can expose it like so:
QThread 的 sleep 方法是受保护的,但您可以像这样公开它:
class SleeperThread : public QThread
{
public:
static void msleep(unsigned long msecs)
{
QThread::msleep(msecs);
}
};
Then just call:
然后只需调用:
SleeperThread::msleep(1000);
from any thread.
从任何线程。
However, a more elegant solution would be to refactor your code to use a QTimer - this might require you saving the state so you know what to do when the timer goes off.
但是,更优雅的解决方案是重构您的代码以使用 QTimer - 这可能需要您保存状态,以便您知道在计时器关闭时该怎么做。
回答by TimW
I don't recommend sleep in a event based system but if you want to ...
You can use a waitcondition, that way you can always interrupt the sleepif neccesary.
我不建议在基于事件的系统中睡眠,但如果你想......
你可以使用等待条件,这样你就可以在必要时随时中断睡眠。
//...
QMutex dummy;
dummy.lock();
QWaitCondition waitCondition;
waitCondition.wait(&dummy, waitTime);
//...
回答by doron
The reason why sleep is a bad idea in event based programming is because event based programming is effectively a form on non-preemptive multitasking. By calling sleep, you prevent any other event becoming active and therefore blocking the processing of the thread.
在基于事件的编程中睡眠是一个坏主意的原因是基于事件的编程实际上是非抢占式多任务处理的一种形式。通过调用 sleep,您可以防止任何其他事件变为活动状态,从而阻止线程的处理。
In a request response scenario for udp packets, send the request and immediately wait for the response. Qt has good socket APIs which will ensure that the socket does not block while waiting for the event. The event will come when it comes. In your case the QSocket::readReady signal is your friend.
在 udp 数据包的请求响应场景中,发送请求并立即等待响应。Qt 具有良好的套接字 API,可确保套接字在等待事件时不会阻塞。该事件将在该事件发生时到来。在您的情况下, QSocket::readReady 信号是您的朋友。
If you want to schedule an event for some point of time in the future, use QTimer. This will ensure that other events are not blocked.
如果您想在将来的某个时间点安排事件,请使用 QTimer。这将确保不会阻止其他事件。
回答by Matteo Italia
I don't know how the QTs handle the events internally, but on most systems at the lowest level the application life goes like this: the main thread code is basically a loop (the message loop), in which, at each iteration, the application calls a function that gives to it a new message; usually that function is blocking, i.e. if there are no messages the function does not return and the application is stopped.
我不知道 QT 是如何在内部处理事件的,但在大多数最低级别的系统上,应用程序的生命周期是这样的:主线程代码基本上是一个循环(消息循环),其中,在每次迭代中,应用程序调用一个函数,给它一条新消息;通常该函数是阻塞的,即如果没有消息该函数不会返回并且应用程序停止。
Each time the function returns, the application has a new message to process, that usually has some recipient (the window to which is sent), a meaning (the message code, e.g. the mouse pointer has been moved) and some additional data (e.g. the mouse has been moved to coords 24, 12).
每次函数返回时,应用程序都有一条新消息要处理,通常有一些接收者(发送到的窗口)、含义(消息代码,例如鼠标指针已移动)和一些附加数据(例如鼠标已移动到坐标 24, 12)。
Now, the application has to process the message; the OS or the GUI toolkit usually do this under the hood, so with some black magic the message is dispatched to its recipient and the correct event handler is executed. When the event handler returns, the internal function that called the event handler returns, so does the one that called it and so on, until the control comes back to the main loop, that now will call again the magic message-retrieving function to get another message. This cycle goes on until the application terminates.
现在,应用程序必须处理消息;操作系统或 GUI 工具包通常在幕后执行此操作,因此使用一些黑魔法将消息分派给其接收者并执行正确的事件处理程序。当事件处理程序返回时,调用事件处理程序的内部函数返回,调用它的内部函数也返回,依此类推,直到控制返回主循环,现在将再次调用神奇的消息检索函数以获取另一个消息。这个循环一直持续到应用程序终止。
Now, I wrote all this to make you understand why sleep is bad in an event driven GUI application: if you notice, while a message is processed no other messages can be processed, since the main thread is busy running your event handler, that, after all, is just a function called by the message loop. So, if you make your event handler sleep, also the message loop will sleep, which means that the application in the meantime won't receive and process any other messages, including the ones that make your window repaint, so your application will look "hang" from the user perspective.
现在,我写这些是为了让您了解为什么在事件驱动的 GUI 应用程序中睡眠不好:如果您注意到,在处理消息时无法处理其他消息,因为主线程正忙于运行您的事件处理程序,即,毕竟,只是一个被消息循环调用的函数。因此,如果您让事件处理程序休眠,消息循环也将休眠,这意味着应用程序在此期间不会接收和处理任何其他消息,包括使您的窗口重新绘制的消息,因此您的应用程序将看起来“挂起”从用户的角度。
Long story short: don't use sleep unless you have to sleep for very short times (few hundreds milliseconds at most), otherwise the GUI will become unresponsive. You have several options to replace the sleeps: you can use a timer (QTimer), but it may require you to do a lot of bookkeeping between a timer event and the other. A popular alternative is to start a separate worker thread: it would just handle the UDP communication, and, being separate from the main thread, it would not cause any problem sleeping when necessary. Obviously you must take care to protect the data shared between the threads with mutexes and be careful to avoid race conditions and all the other kind of problems that occur with multithreading.
长话短说:除非您必须睡眠很短的时间(最多几百毫秒),否则不要使用睡眠,否则 GUI 将变得无响应。您有多种替代sleep的选项:您可以使用计时器(QTimer),但它可能需要您在计时器事件和另一个事件之间进行大量记录。一个流行的替代方法是启动一个单独的工作线程:它只处理 UDP 通信,并且与主线程分开,在必要时不会导致任何睡眠问题。显然,您必须小心保护具有互斥锁的线程之间共享的数据,并小心避免竞争条件和多线程发生的所有其他类型的问题。