执行"等待回调"在等待std :: condition_variable被通知期间

时间:2015-11-05 07:59:28

标签: multithreading qt c++11 condition-variable stdthread

我以这种方式使用std :: condition_variable:

var length = [$('.first'), $('.second'), $('.third'), $('.fourth'), $('.one'), $('.two'), $('.three'), $('.four')];
length.css("min-height",$(window).height());

我对此非常满意,但现在我想执行一些代码"在等待期间" (我不知道我是否可以这样说,但这是想法),例如更新GUI或增加等待计数器,或其他任何东西。

说我们正在使用Qt,我尝试过这样的事情:

void wait()
{
    std::unique_lock<std::mutex> lock(m_stateCompletedMutex);

    m_waitCondition.wait(lock, [this](){return (m_state == STATE_COMPLETED);});
}

这里的目标是在等待工作线程完成时保持GUI响应(至少对系统事件而不是用户输入)。

我对此代码有两个问题:

1 /这是做到这一点的好方法,还是有更好的方法来执行代码&#34;等待&#34;

2 /执行&#34;等待代码&#34;的频率(我的例子中的qApp-&gt; processEvents调用)?它是系统依赖的吗?或者它取决于当前的CPU负载或其他什么?或者我应该使用m_waitCondition。 wait_for 来确保最低频率呼叫?

关于第2点/,我已经测试过监控它(使用std :: chrono :: high_resolution_clock)并且我的应用程序中的延迟似乎在200ms到4000ms之间,我认为这是一个很大的范围

2 个答案:

答案 0 :(得分:1)

不,这不是正确的方法。您绝不能在Qt(或任何事件驱动的框架)中的Main(GUI)线程上等待或睡眠。

GUI线程必须接收某种事件,而不是等待。如果所有内容都是Qt(即不是某些外部代码片段无法被Qt-isms污染),那么只需让另一个线程在完成时发出信号。

否则,您可以采用user1034749的方法,并将回调传递给计算函数。反过来,该回调可以设置一个标志,或者坚持Qt的事件驱动性质,发出一个信号,沿着你的GUI产生下一步(即显示计算结果)。

如果您致电ProcessEvents()您可能会做错,那么很有可能。

答案 1 :(得分:0)

  

1 /这是做到这一点的好方法,还是有一种更好的方法来“等待”时执行代码

至于我,这样做的“好方法”将是从程序的GUI部分隐藏计算架构的细节。例如,界面可能是这样的:

extern void calc_something(Params, const std::function<void ()> &end_calc_callback);

其中end_calc_callback可以在另一个(非GUI)线程上下文中调用。

所以用法就像这样

std::atomic<bool> result_ready{false};
calc_something(Params(), [&result_ready]() { result_ready = true; });
//wait result_ready
  

2 /执行“等待代码”的频率(我的&gt;示例中的qApp-&gt; processEvents调用)?它是系统依赖的吗?

您可以为QCoreApplication::processEvents设置最长工作时间,请参阅有关此问题的Qt文档,设置超时的时间取决于您的代码和用户, 例如,让你有这样的代码:

std::atomic<bool> result_ready{false};
calc_something(Params(), [&result_ready]() { result_ready = true; });
ProgressWindow pw;
pw.show();
while (!result_ready)
  qApp->processEvents(QEventLoop::ExcludeUserInputEvents, timeout);

让我们假设您在ProgressWindow计时器中绘制一些动画, 人类可以对屏幕上的某些内容做出响应,延迟让我们说200毫秒(https://en.wikipedia.org/wiki/Mental_chronometry)然后取决于什么动画 你在ProgressWindow中显示,用户反应你可以选择超时。