[英]Thread safety of calling QObject's method from another (non-qt) thread?
I have two objects which lives in different threads and I'm trying to figure if a pattern used is thread safe or not. 我有两个对象,它们存在于不同的线程中,我试图确定使用的模式是否是线程安全的。
The first object is QObject-derived and lives (was created in) the main Qt thread. 第一个对象是QObject派生的并且在主Qt线程中存在(在其中创建)。 The class contains some
Q_INVOKABLE
methods that should be called from QML, some signal*()
methods defined as signals:
and some Emit*()
(normal) methods that I use as wrappers to emit signals. 该类包含一些应该从QML调用的
Q_INVOKABLE
方法,一些定义为signals:
signal*()
方法signals:
以及一些Emit*()
(普通)方法,我用它作为包装器发出信号。 For example: 例如:
void MyQObjectClass::EmitStatus(void) {
emit signalStatusChange(_status);
}
I normally listen for those signals in QML. 我通常在QML中监听这些信号。
The second object is not QObject-derived and lives in a second thread ( pthread
). 第二个对象不是 QObject派生的, 而是存在于第二个线程(
pthread
)中。 This thread runs its own event loop (libev) and dispatches events. 该线程运行自己的事件循环(libev)并调度事件。 I can't use anything related to Qt in this thread because I need the custom
libev
event loop. 我不能在这个线程中使用与Qt相关的任何东西,因为我需要自定义
libev
事件循环。 On this object I defined some Notify*()
methods that will send async events through libev
to be picked up by callbacks. 在这个对象上,我定义了一些
Notify*()
方法,这些方法将通过libev
发送异步事件,以便回调。
I need to be able to communicate between the two objects/threads, but I'm not sure how to safely do this. 我需要能够在两个对象/线程之间进行通信,但我不确定如何安全地执行此操作。
The actual design is to let the pthread
thread object call the different Emit*()
methods directly so that the QObject can properly propagate the information to Qt/QML. 实际设计是让
pthread
线程对象直接调用不同的Emit*()
方法,以便QObject可以正确地将信息传播到Qt / QML。 If I need to send information from Qt/QML to the pthread
/ libev
object I call (from the Qt thread) the Notify*()
methods. 如果我需要将信息从Qt / QML发送到
pthread
/ libev
对象,我会调用(来自Qt线程) Notify*()
方法。
When reading Accessing QObject Subclasses from Other Threads , it says: 从其他线程读取访问QObject子类时 ,它说:
QObject and all of its subclasses are not thread-safe.
QObject及其所有子类都不是线程安全的。 This includes the entire event delivery system.
这包括整个事件传递系统。
but then further it is stated that: 但随后进一步说明:
On the other hand, you can safely emit signals from your QThread::run() implementation, because signal emission is thread-safe.
另一方面,您可以安全地从QThread :: run()实现中发出信号,因为信号发射是线程安全的。
So my question is, is the design described above thread-safe? 所以我的问题是,上面描述的设计是线程安全的吗? Can I safely call
myQObject->EmitMySignal()
, which in turns will call emit signalMySignal()
, all this from inside the pthread
object? 我可以安全地调用
myQObject->EmitMySignal()
,它会从pthread
对象内部调用emit signalMySignal()
吗?
I will demonstrate how to achieve what you want with events instead of signals and slots that you cannot use (because one side is not QObject
derived) 我将演示如何用事件而不是你不能使用的信号和插槽来实现你想要的东西(因为一方不是
QObject
派生的)
class MyObjectClass : public QObject
{
Q_OBJECT
public:
virtual bool event(QEvent *event) override
{
bool result = true;
if(event->type() == QEvent::User+1)
emit signalStatusChange(_status);
else
result = QObject::event(event); //call direct parent's event here!
return result;
}
};
And in your other thread you will do this: 在你的另一个主题中你会这样做:
MyObjectClass *p; //holds pointer to the instance in main thread
qApp->postEvent(p, new QEvent(QEvent::User+1));
This will retrieve pointer to the app that lives in the main thread and post event to its event loop. 这将检索指向存在于主线程中的应用程序的指针,并将事件发布到其事件循环中。 The event will be processed asynchronously from the call however so the behaviour will be different than what you are doing now.
事件将从调用异步处理,但行为将与您现在所做的不同。 But it will be safer and imho more elegant.
但它会更安全,更优雅。 You can add as many types as you need.
您可以根据需要添加任意数量的类型。 Do not forget to propagate the event to the parent if you have not handled it though!
如果您没有处理它,请不要忘记将事件传播给父级!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.