Multithreading 执行一个;“等待回调”;在等待std::condition_变量被通知期间
我使用std::condition\u变量的方式如下: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
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);