Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 执行一个;“等待回调”;在等待std::condition_变量被通知期间_Multithreading_Qt_C++11_Condition Variable_Stdthread - Fatal编程技术网

Multithreading 执行一个;“等待回调”;在等待std::condition_变量被通知期间

Multithreading 执行一个;“等待回调”;在等待std::condition_变量被通知期间,multithreading,qt,c++11,condition-variable,stdthread,Multithreading,Qt,C++11,Condition Variable,Stdthread,我使用std::condition\u变量的方式如下: void wait() { std::unique_lock<std::mutex> lock(m_stateCompletedMutex); m_waitCondition.wait(lock, [this](){return (m_state == STATE_COMPLETED);}); } void wait() { std::unique_lock lock(m_stateCompletedMute

我使用std::condition\u变量的方式如下:

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

    m_waitCondition.wait(lock, [this](){return (m_state == STATE_COMPLETED);});
}
void wait()
{
std::unique_lock lock(m_stateCompletedMutex);
waitCondition.wait(lock,[this](){return(m_state==state_COMPLETED);});
}
我对此非常满意,但现在我想在“等待期间”执行一些代码(我不知道是否可以这样说,但这就是想法),例如更新GUI或增加等待计数器,或其他任何操作

说我们使用的是Qt,我尝试过这样的方法:

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

    while (m_state != STATE_COMPLETED)
    {
        m_waitCondition.wait(lock);

        // Use this an example, it could be any code, executed in the waiting thread
        qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
    }
}
void wait()
{
std::unique_lock lock(m_stateCompletedMutex);
while(m_state!=state_COMPLETED)
{
m_waitCondition.wait(锁);
//举个例子,它可以是在等待线程中执行的任何代码
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
}
}
这里的目标是在等待工作线程完成时保持GUI的响应性(至少对系统事件,而不是用户输入)

关于此代码,我有两个问题:

1/这是一种很好的方法,还是有更好的方法“在等待时”执行代码

2/多久执行一次“等待代码”(在我的示例中是qApp->processEvents调用)?它依赖于系统吗?还是取决于当前的CPU负载或其他因素?或者我应该使用m_waitCondition.等待以确保呼叫频率最低

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

1/这是一种很好的方法,还是有更好的方法“在等待时”执行代码

对我来说,“好办法”是在程序的GUI部分隐藏计算架构的细节。例如,接口可能如下所示:

extern void calc_something(Params, const std::function<void ()> &end_calc_callback);
2/多久执行一次“等待代码”(我的>示例中的qApp->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);
std::原子结果_ready{false};
计算某物(Params(),[&result\u ready](){result\u ready=true;});
进步窗;
show();
而(!result_ready)
qApp->processEvents(QEventLoop::ExcludeUserInputEvents,超时);
假设你在ProgressWindow中有一个计时器来绘制一些动画, 人类可以对屏幕上的某些东西做出延迟的反应,比如说200毫秒(),然后取决于什么动画
在ProgressWindow中显示,用户反应可以选择超时。

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

GUI线程必须接收某种类型的事件,而不是等待。如果一切都是Qt(即不是某些不能被Qt-isms“污染”的外部代码段),那么只需让另一个线程在完成时发出信号即可

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


如果调用的是
ProcessEvents()
,则很可能是错误的。

对于“等待时”执行代码,您需要创建新线程或进程。设计中有10个线程是可以的,其中9个线程在给定时刻等待。通常
.wait()
仅在相应的
调用后返回。notify
调用。虚假的醒来其实很少见。“虚假的醒来其实很少见”:我也这么想。但是我已经用一个运行时间计数器测试了控制台的一个输出(而不是我的示例中的qApp->processEvents调用),消息大约每200-4000ms写入控制台一次。也就是说,您的
.wait()
只会每隔200-4000ms被虚假唤醒一次(在其他线程中没有
.notify()
调用)。在我的示例中,qApp->processEvents每200-4000ms?调用一次,没有任何notify()。最简单的解决方案不是使用条件变量,而是让代码在执行任何操作时发出信号。信号发射可以通过API作为模板类型用户提供的functor的调用公开。谢谢,但是关于第2点,我知道可以使用超时参数调用processEvents。我的问题不是这个代码被调用多长时间,而是调用的频率。我的意思是,即使不是“processEvents”,两个调用之间的延迟是多少。在我的例子中,我看到每次调用之间有200ms-4000ms的延迟,即使调用只是一条发送到控制台的消息(不是processEvent调用)。怎么开这个延迟?多久叫什么?处理事件的工作时间<代码>有多长?多久处理一次,而不是多长时间。在我的例子中,我看到每次调用之间有200ms-4000ms的延迟,即使调用只是一条发送到控制台的消息(不是processEvent调用)。这种延迟是如何驱动的?如果您使用绝对时钟来测量,而不是进程时钟来测量,那么它取决于系统负载加上要处理的事件量。为了解决这个问题,例如,与GUI线程相比,您可以降低计算线程的优先级,这应该有助于减少
processEvents
调用之间的延迟。
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);