在持久性QThread工作人员完成一轮工作时有效地阻止函数执行
我的问题是,在Qt中似乎没有一种有效的方法来知道持久QThread线程何时完成了一轮的工作。所谓持久性,我的意思是QThread在完成一些工作后不会死亡 我使用这种线程样式的持久线程在持久性QThread工作人员完成一轮工作时有效地阻止函数执行,qt,qthread,Qt,Qthread,我的问题是,在Qt中似乎没有一种有效的方法来知道持久QThread线程何时完成了一轮的工作。所谓持久性,我的意思是QThread在完成一些工作后不会死亡 我使用这种线程样式的持久线程 class Worker : public QObject { Q_OBJECT public slots: void doWork() { /* ... */ } }; QThread *threadA = new QThread; QThread *threadB =
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork() {
/* ... */
}
};
QThread *threadA = new QThread;
QThread *threadB = new QThread;
Worker *workerA = new Worker;
Worker *workerB = new Worker;
workerA->moveToThread(threadA);
workerB->moveToThread(threadB);
threadA->start();
threadB->start();
QMetaObject::invokeMethod(workerA, "doWork", Qt::QueuedConnection);
QMetaObject::invokeMethod(workerB, "doWork", Qt::QueuedConnection);
我有这样一个场景:
//Outside force (OS/driver) calls this very frequently.
//Gets called a lot so want to re-use threads instead of creating new
//threads each time.
C callback function(some parameters)
{
//STEP 1
//Feed 2 threads with computational expensive work.
//threads should be pre-made threads to save time on thread creation.
//do not terminate threads because they will be re-used next time C callback
//function
//is called with a new round of work.
//STEP 2
//Need to pause/wait/BLOCK function execution here until the 2 worker threads
//have completed the work.
//THIS IS THE PROBLEM! No efficient way to block! I don't see how a signal/slot
//can be used for this purpose.
//STEP3
//After 2 threads complete their assigned work, resume execution of this C
//callback function.
//Perform some non-threaded work in this function to complete the job.
//return (end function execution), all work for this round/call is complete.
}
问题在于,对于持久性线程,无法按照上述伪代码中的说明进行阻塞
我不能调用QThread::wait(),因为在非持久性线程场景中,它只能用于阻塞,直到工作完成。wait()等待线程死亡。。。使它对我的需要毫无用处。对我来说,wait()只是永远等待,因为我的线程不会死
我不认为信号槽的东西可以用来阻挡,至少我不知道怎么做。也许有一些不明显的事件技巧。我意识到我可以有一个繁忙的wile循环来检查一些由工作线程操纵的标志,但是这会占用线程的CPU时间
如果您知道一种使用持久性QThread线程进行阻塞的有效方法,我将非常感谢您提供一个代码示例来说明如何实现这一点 在调用
doWork
之前,可以使用计数器为0的QSemaphore
,主线程使用信号量等待。acquire(2)代码>和每个工人调用信号量。释放(1)代码>工作完成时。
因此,只有当两个辅助线程完成时,主线程才会唤醒。
您可以在开始工作后调用的Worker
对象中添加一个不执行任何操作的插槽:
QMetaObject::invokeMethod(workerA, "doWork", Qt::QueuedConnection);
QMetaObject::invokeMethod(workerB, "doWork", Qt::QueuedConnection);
QMetaObject::invokeMethod(workerA, "doNothing", Qt::BlockingQueuedConnection;
QMetaObject::invokeMethod(workerB, "doNothing", Qt::BlockingQueuedConnection);
Qt::BlockingQueuedConnection
意味着invokeMethod
将被阻塞,直到它能够真正调用插槽doNothing()
并返回
您可以运行QEventLoop
,并在收到信号时使其退出:
QEventLoop loop;
// the connection have to be made before running the tasks
// to avoid race condition in case the task is very short
loop.connect(workerA, SIGNAL(finished()), &loop, SLOT(quit()));
loop.connect(workerB, SIGNAL(finished()), &loop, SLOT(quit()));
QMetaObject::invokeMethod(workerA, "doWork", Qt::QueuedConnection);
QMetaObject::invokeMethod(workerB, "doWork", Qt::QueuedConnection);
// the loop will be interrupted once for each worker
for(int i=0; i < 2; ++i) {
loop.exec();
}
QEventLoop循环;
//必须在运行任务之前建立连接
//在任务非常短的情况下避免竞争条件
连接(工作区、信号(finished())、循环、插槽(quit());
连接(workerB,信号(finished()),&loop,插槽(quit());
QMetaObject::invokeMethod(workerA,“doWork”,Qt::QueuedConnection);
QMetaObject::invokeMethod(workerB,“doWork”,Qt::QueuedConnection);
//循环将为每个工人中断一次
对于(int i=0;i<2;++i){
loop.exec();
}
在调用doWork
之前,可以使用计数器为0的QSemaphore
,主线程使用信号量等待。获取(2)代码>和每个工人调用信号量。释放(1)代码>工作完成时。
因此,只有当两个辅助线程完成时,主线程才会唤醒。
您可以在开始工作后调用的Worker
对象中添加一个不执行任何操作的插槽:
QMetaObject::invokeMethod(workerA, "doWork", Qt::QueuedConnection);
QMetaObject::invokeMethod(workerB, "doWork", Qt::QueuedConnection);
QMetaObject::invokeMethod(workerA, "doNothing", Qt::BlockingQueuedConnection;
QMetaObject::invokeMethod(workerB, "doNothing", Qt::BlockingQueuedConnection);
Qt::BlockingQueuedConnection
意味着invokeMethod
将被阻塞,直到它能够真正调用插槽doNothing()
并返回
您可以运行QEventLoop
,并在收到信号时使其退出:
QEventLoop loop;
// the connection have to be made before running the tasks
// to avoid race condition in case the task is very short
loop.connect(workerA, SIGNAL(finished()), &loop, SLOT(quit()));
loop.connect(workerB, SIGNAL(finished()), &loop, SLOT(quit()));
QMetaObject::invokeMethod(workerA, "doWork", Qt::QueuedConnection);
QMetaObject::invokeMethod(workerB, "doWork", Qt::QueuedConnection);
// the loop will be interrupted once for each worker
for(int i=0; i < 2; ++i) {
loop.exec();
}
QEventLoop循环;
//必须在运行任务之前建立连接
//在任务非常短的情况下避免竞争条件
连接(工作区、信号(finished())、循环、插槽(quit());
连接(workerB,信号(finished()),&loop,插槽(quit());
QMetaObject::invokeMethod(workerA,“doWork”,Qt::QueuedConnection);
QMetaObject::invokeMethod(workerB,“doWork”,Qt::QueuedConnection);
//循环将为每个工人中断一次
对于(int i=0;i<2;++i){
loop.exec();
}
我认为QWaitCondition是您的朋友。或者返回事件循环,而不是阻塞,并从完成的线程发送信号,以触发等待线程(在插槽中)中的继续。我认为QWaitCondition是您的朋友。或者返回事件循环,而不是阻塞,并从完成的线程发送信号,以触发等待线程(在插槽中)中的继续。