在 QThread 上下文中调用方法
在我的应用程序中,有主线程和工作线程 (QThread
)。
我想从主线程调用工作线程的方法并让它在线程的上下文中运行。
我尝试使用 QMetaObject::invokeMethod
并为其提供 QueuedConnection
选项,但它不起作用。
我还尝试从主线程(连接到工作线程的插槽)发出信号,但也失败了。
以下是我尝试过的大致片段:
class Worker : public QThread
{
Q_OBJECT
public:
Worker() { }
void run()
{
qDebug() << "new thread id " << QThread::currentThreadId();
exec();
}
public slots:
void doWork()
{
qDebug() << "executing thread id - " << QThread::currentThreadId();
}
};
使用 QMetaObject 方式:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "main thread id - " << QThread::currentThreadId();
Worker worker;
worker.start();
QMetaObject::invokeMethod(&worker, "doWork", Qt::QueuedConnection);
return a.exec();
}
使用信号方式:
class Dummy : public QObject
{
Q_OBJECT
public:
Dummy() { }
public slots:
void askWork() { emit work(); }
signals:
void work();
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "main thread id - " << QThread::currentThreadId();
Worker worker;
worker.start();
Dummy dummy;
QObject::connect(&dummy, SIGNAL(work()), &worker, SLOT(doWork()), Qt::QueuedConnection);
QTimer::singleShot(1000, &dummy, SLOT(askWork()));
return a.exec();
}
这两种方式都会导致主线程 id 打印在 QThread
doWork
中。
另外,我想过实现一个简单的生产者-消费者,但如果这有效,有什么理由不这样做呢?
In my application there's the main thread and a worker thread (QThread
).
From the main thread I'd like to invoke a method of my worker thread and have it run in the thread's context.
I've tried using QMetaObject::invokeMethod
and give it the QueuedConnection
option but it's not working.
I've also tried emitting signals from the main thread (which is connected to the worker thread's slot) but that also failed.
Here's a snippet of roughly what I tried:
class Worker : public QThread
{
Q_OBJECT
public:
Worker() { }
void run()
{
qDebug() << "new thread id " << QThread::currentThreadId();
exec();
}
public slots:
void doWork()
{
qDebug() << "executing thread id - " << QThread::currentThreadId();
}
};
Using the QMetaObject way:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "main thread id - " << QThread::currentThreadId();
Worker worker;
worker.start();
QMetaObject::invokeMethod(&worker, "doWork", Qt::QueuedConnection);
return a.exec();
}
Using the signal way:
class Dummy : public QObject
{
Q_OBJECT
public:
Dummy() { }
public slots:
void askWork() { emit work(); }
signals:
void work();
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "main thread id - " << QThread::currentThreadId();
Worker worker;
worker.start();
Dummy dummy;
QObject::connect(&dummy, SIGNAL(work()), &worker, SLOT(doWork()), Qt::QueuedConnection);
QTimer::singleShot(1000, &dummy, SLOT(askWork()));
return a.exec();
}
Both ways result in the main thread id being printed in the QThread
doWork
.
Also, I thought of implementing a simple producer-consumer but if this works, is there any reason why not to do it this way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
此示例展示了如何拆分 Worker 类,以使其按照您的需要工作。 您还需要提供对 Worker 实例的引用或指针才能连接到插槽。
This example shows how you can split up the Worker class, to make it work as you want. You also need to make available a reference or pointer to the Worker instance to be able to connect to the slot.
问题在于接收者(QThread)“存在”于主线程中,因此主线程的事件循环是执行该槽的事件循环。
来自 Qt 的文档:
所以到目前为止我找到的解决方案是在线程的 run() 内部创建一个对象并使用它的插槽。 这样,接收者的所有者就是线程,然后在线程上下文中调用槽。
The problem was that the receiver (the QThread) 'lives' in the main thread and thus the main thread's event loop is the one that executes the slot.
from Qt's docs:
So the solution I found so far was to create an object inside the thread's run() and use its slots instead. That way the receiver's owner is the thread and then the slot is called in the threads context.
对于简单的生产者-消费者示例,请查看 Bradley T. Hughes 的博客文章 行走时不头痛。
For the simple producer-consumer example, have a look at the blog entry from Bradley T. Hughes Treading without the headache.
Worker 是在主线程中创建的,因此它的事件是在主线程中处理的。 您必须将 Worker 移动到它自己的线程:
现在 Qt 知道
worker
位于新线程中,并将在该事件循环中对事件进行排队。The Worker is created in the main thread, and therefore it's events are proccessed in the main thread. You must move the Worker to it's own thread:
Now Qt knows
worker
lives in the new thread, and will queue events in that event loop.看起来您的工作线程在您调用任何函数或向其发送信号之前就已完成。
It looks like your worker thread completes before you can even invoke any function or send a signal to it.