制作人:
// it is in the GUI thread
...
MtileLoadQueue.lock();
{
if(!tileLoadQueue.contains(task))
{
MtileToload.lock();
++tilesToload;
MtileToload.unlock();
tileLoadQueue.enqueue(task);
loaderLimit.release();//loaderLimit is a semaphore
}
}
MtileLoadQueue.unlock();
消费者它的子类是QThread:
consumer::run(){
while (!finish)
{
loaderLimit.acquire();//loaderLimit is a semaphore
LoadTask task;
MtileLoadQueue.lock();
{
if (tileLoadQueue.count() > 0)
{
task = tileLoadQueue.dequeue();
}
}
MtileLoadQueue.unlock();
//deal with the task...
Mfinish.lock();
finish = quit; //quit is initialized as false
Mfinish.unlock();
}
}
当我希望使用者QThread完成它的任务(允许运行函数返回)时,我这样做了(从GUI线程):
Mquit.lock();
quit = true;
Mquit.unlock();
loaderLimit.release();
wait();
然后run()函数可以返回,使用者线程完成它的工作。
这种方法的正确性如何?关于如何退出消费者线程,有没有更好的解决方案,因为我担心退出时是否会出现死锁。
根据队列元素的类型,可以有许多解决方案。
-
如果元素是指针—和
nullptr
永远不可能是有效对象,那么生产者可能会将nullptr
(通常称为中毒对象)添加到队列中,以便通知消费者退出。请注意,如果有许多使用者,则每个使用者必须在退出之前再次将nullptr
添加到队列中,以便通知其他使用者。 -
如果元素是多态对象(指针1或引用),则生产者可以使用
poison_task
的对象来通知消费者。 -
如果元素既不是指针也不是多态引用,则:
- 生产者可以使用sentinel值进行通知
- 元素类型可以是CCD_ 5,其中空的可选值可以用作毒药对象
- 元素类型可以是
std::pair<bool,T>
,其中.first
表示.second
是有效对象还是毒药。注意,在这种情况下,T
必须是默认可构造的
使用任何适合您的情况。
1.注意,在这种情况下,您可以使用nullptr
,因为对象是指针
如果工作线程正在轮询状态变量并对其进行评估,是的,这是可能的。然而,GUI线程可以直接设置它:
InstanceOfWorkerThread->m_quit = true; //quit is bad symbol as reserved by QThread itself
这是礼貌地要求线程终止的方式。线程可以忽略"建议"。此外,它只有在下次计算退出变量时才会终止。
您也可以通过调用以下之一来停止线程:
void QThread::exit ( int returnCode = 0 )
void QThread::quit ()
void QThread::terminate ()