我的问题是,在Qt中似乎没有一种有效的方法可以知道持续 QThread线程何时完成轮次工作。持久性我的意思是QThreads在完成一些工作后不会死亡。
我正在使用具有此线程样式的持久线程。
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.
}
问题是,对于 PERSISTENT 线程,无法阻止,如上面的伪代码所述。
我无法调用QThread :: wait(),因为只有在NON-PERSISTENT THREADS场景中完成工作之前,它才能用于阻塞。 wait()等待直到线程死...让它对我的需求毫无用处。对我来说,wait()只是永远等待,因为我的线程不会死。
我不认为信号槽的东西可以用来阻塞,至少我看不出怎么样。也许有一些非明显的事件技巧。我意识到我可以有一个繁忙的wile循环来检查一些由工作线程操纵的标志,但这会使CPU时间远离线程。
如果您知道使用持久性QThread线程阻止的有效方法,我真的很感激如何完成此操作的代码示例。
答案 0 :(得分:1)
在调用QSemaphore
之前,您可以使用带有计数器的doWork
,主线程等待semaphore.acquire(2);
,每个工作人员在工作时调用semaphore.release(1);
完成。
因此,只有当2名工人完成时,主线程才会被唤醒。
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();
}