Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.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
在持久性QThread工作人员完成一轮工作时有效地阻止函数执行_Qt_Qthread - Fatal编程技术网

在持久性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 =

我的问题是,在Qt中似乎没有一种有效的方法来知道持久QThread线程何时完成了一轮的工作。所谓持久性,我的意思是QThread在完成一些工作后不会死亡

我使用这种线程样式的持久线程

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是您的朋友。或者返回事件循环,而不是阻塞,并从完成的线程发送信号,以触发等待线程(在插槽中)中的继续。