Rob*_*ohr 4 c++ qt multithreading
我从派生的类QObject,UploadWorker使用的Qt文档中示范运行中的线程任务的推荐方式,已启动.
QThread* thread = new QThread();
UploadWorker* worker = new UploadWorker();
worker->moveToThread(thread);
connect(thread, SIGNAL(started()), worker, SLOT(doWork()));
Run Code Online (Sandbox Code Playgroud)
现在,这完全正常.UploadWorker然后,我尝试Uploader使用相同的技术为自己创建一名工人.
以下是标题的必要部分.
class UploadWorker : public QObject
{
Q_OBJECT
public:
// stuff
public slots:
void doWork();
signals:
void allWorkDone();
protected:
void startUploader();
};
class Uploader : public QObject
{
Q_OBJECT
public:
// stuff
public slots:
void doWork();
void finishWhenQueueIsEmpty();
};
Run Code Online (Sandbox Code Playgroud)
这是执行UploadWorker.
void
UploadWorker::doWork()
{
// This method is called when QThread emits started()
// Prepare the upload thread
startUploader();
// Do some important work...
// Notify the upload thread that we're done
emit allWorkDone();
}
void
UploadWorker::startUploader()
{
QThread* thread = new QThread();
Uploader* uploader = new Uploader();
uploader->moveToThread(thread);
connect(this, SIGNAL(stopped()), uploader, SLOT(stop()));
connect(uploader, SIGNAL(finished()), thread, SLOT(quit()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
connect(uploader, SIGNAL(finished()), uploader, SLOT(deleteLater()));
connect(thread, SIGNAL(started()), uploader, SLOT(doWork()));
connect(this, SIGNAL(allWorkDone()),
uploader, SLOT(finishWhenQueueIsEmpty()));
thread->start();
}
Run Code Online (Sandbox Code Playgroud)
我现在的问题是,Uploader::finishWhenQueueIsEmpty()插槽永远不会被触发.除非:我删除uploader->moveToThread(thread);.
错误在哪里?
编辑
我忘了提到Uploader::doWork()线程启动时调用该方法.这是任何其他插槽,在此示例finishWhenQueueIsEmpty()中不起作用.
我修改了关于插槽名称的拼写错误.
一个非常可能的可能性是你正在执行你的Uploader::doWork()插槽并等待调用插槽Uploader::finishWhenQueueIsEmpty()来完成它的执行,通过一些同步机制(isRunning例如一个布尔值).
您需要做的是连接您的插槽,如下所示:
connect(this, SIGNAL(allWorkDone()),
uploader, SLOT(finishWhenQueueIsEmpty()),
Qt::DirectConnection);
Run Code Online (Sandbox Code Playgroud)
并finishWhenQueueIsEmpty()使用互斥锁保护同步机制.
为什么?
因为在不同线程中的对象之间建立连接的默认模式是Qt::QueuedConnection.它在这里做的是Uploader这里的类的每个槽都排队等待执行,也就是说,一旦线程返回到事件循环(即当前槽已经完成运行),队列中的下一个槽将运行.然后,这意味着在这种模式下,调用Uploader::doWork()然后Uploader::finishWhenQueueIsEmpty()将导致程序陷入困境doWork().
使用Qt::DirectConnection,插槽将在运行的线程中运行,UploaderWorker::doWork()并且可以在运行时实际Uploader::doWork()运行.但是,您有两个可以访问同一Uploader对象的线程,因此您需要保护对该对象的每个部分的访问/写入.
| 归档时间: |
|
| 查看次数: |
2743 次 |
| 最近记录: |