等待QThread时会UI阻塞/如何正确使用QThread
Will UI block when waiting for QThread / How to use QThread properly
如果我在 ui 线程 (window) 中有一个进度条,它将 运行 无穷无尽,直到一个方法完成它的工作,ui 线程是否会阻塞如果我正在等待第二个 QThread 完成,那么进度条呢?如果 ui 线程阻塞等待,那么我不会等待第二个线程。我想实现一个回调方法,该方法将在第二个线程完成时调用,但随后:如何连接到回调方法?
我想做什么?
我有一个 window,这个 window 有一个首先不可见的进度条。当用户按下某个按钮请求数据时,将调用一个方法,其中 returns 一个 RequestPointer 包含一个 returns 请求状态的方法。
当用户按下按钮时,我想让进度条可见,运行 无限地直到请求完成,我可以将数据打印到 window。
我想将此指针传递给工作人员,工作人员会检查一个 while(标志)循环,如果状态仍然是 运行ning,如果是,则休眠。当工人完成后,我想停止进度条并使其再次不可见。我是否必须将进度条传递给线程,或者我可以等待线程而不阻塞 ui?
我不是 Qt 专家ui。真的很新。我试图从 https://doc.qt.io/Qt-5/qthread.html 网站获取一些信息,但我有点难以理解代码示例。
我的工人中的方法class:
void Worker::watchRequest(RequestPtr r_ptr)
{
bool exit = true;
while (!exit)
{
ErrorCode errorCode = r_ptr->Test();
switch (errorCode)
{
case Request_RUNNING:
QThread::msleep(10);
break;
case Request_ABORTED:
exit = true;
break;
case Request_SUCCESS:
exit = true;
break;
}
}
如果您不想阻塞用户界面,您只需在 while 循环中调用 QApplication::processEvents();
。
我有一些代码使用 std::future 而不是 QThread,我的代码如下所示:
while (!progressIndicator->UserBreak()
&& (future.wait_for(std::chrono::seconds(0)) != std::future_status::ready))
{
QApplication::processEvents();
}
这个效果很好。
QThread
有一个 finished
信号。将此连接到某个适当的插槽,这将触发线程完成时所需的任何操作。
我想了解进度的最佳人选是工作线程本身。您可以创建自己的信号,将当前进度发送到某个插槽,该插槽将适当地更新进度条。
或者,您可以使用 QTimer
不时读取当前进度(这与您现在拥有的更接近,但不会阻止 UI)。
要在操作 运行 时更新 UI 线程的进度条,请使用 QTimer 对象来增加进度条的值(最大值将为:当操作完成)。还可以通过 Signal/Slot 方法将 QThread 连接到插槽,以便在操作结束时向 UI 线程发出信号。当QThread完成操作后,向UIThread中的一个Slot发送信号,这将设置进度条的最终值,同时停止QTimer。
如果我在 ui 线程 (window) 中有一个进度条,它将 运行 无穷无尽,直到一个方法完成它的工作,ui 线程是否会阻塞如果我正在等待第二个 QThread 完成,那么进度条呢?如果 ui 线程阻塞等待,那么我不会等待第二个线程。我想实现一个回调方法,该方法将在第二个线程完成时调用,但随后:如何连接到回调方法?
我想做什么? 我有一个 window,这个 window 有一个首先不可见的进度条。当用户按下某个按钮请求数据时,将调用一个方法,其中 returns 一个 RequestPointer 包含一个 returns 请求状态的方法。 当用户按下按钮时,我想让进度条可见,运行 无限地直到请求完成,我可以将数据打印到 window。 我想将此指针传递给工作人员,工作人员会检查一个 while(标志)循环,如果状态仍然是 运行ning,如果是,则休眠。当工人完成后,我想停止进度条并使其再次不可见。我是否必须将进度条传递给线程,或者我可以等待线程而不阻塞 ui?
我不是 Qt 专家ui。真的很新。我试图从 https://doc.qt.io/Qt-5/qthread.html 网站获取一些信息,但我有点难以理解代码示例。
我的工人中的方法class:
void Worker::watchRequest(RequestPtr r_ptr)
{
bool exit = true;
while (!exit)
{
ErrorCode errorCode = r_ptr->Test();
switch (errorCode)
{
case Request_RUNNING:
QThread::msleep(10);
break;
case Request_ABORTED:
exit = true;
break;
case Request_SUCCESS:
exit = true;
break;
}
}
如果您不想阻塞用户界面,您只需在 while 循环中调用 QApplication::processEvents();
。
我有一些代码使用 std::future 而不是 QThread,我的代码如下所示:
while (!progressIndicator->UserBreak()
&& (future.wait_for(std::chrono::seconds(0)) != std::future_status::ready))
{
QApplication::processEvents();
}
这个效果很好。
QThread
有一个 finished
信号。将此连接到某个适当的插槽,这将触发线程完成时所需的任何操作。
我想了解进度的最佳人选是工作线程本身。您可以创建自己的信号,将当前进度发送到某个插槽,该插槽将适当地更新进度条。
或者,您可以使用 QTimer
不时读取当前进度(这与您现在拥有的更接近,但不会阻止 UI)。
要在操作 运行 时更新 UI 线程的进度条,请使用 QTimer 对象来增加进度条的值(最大值将为:当操作完成)。还可以通过 Signal/Slot 方法将 QThread 连接到插槽,以便在操作结束时向 UI 线程发出信号。当QThread完成操作后,向UIThread中的一个Slot发送信号,这将设置进度条的最终值,同时停止QTimer。