我有两个对象,它们生活在不同的线程中,我试图确定一个使用的模式是否是线程安全的。从另一个(非qt)线程调用QObject方法的线程安全性?
第一个对象是QObject派生的,并且生存在(创建于)主Qt线程中。该类包含应该从QML调用的一些Q_INVOKABLE
方法,定义为signals:
的一些signal*()
方法和我用作包装发射信号的一些Emit*()
(正常)方法。例如:
void MyQObjectClass::EmitStatus(void) {
emit signalStatusChange(_status);
}
我通常会在QML中监听这些信号。
第二个对象是而不是 QObject派生并且存在于第二个线程中(pthread
)。该线程运行自己的事件循环(libev)并分派事件。我不能在这个线程中使用任何与Qt相关的东西,因为我需要自定义的libev
事件循环。在这个对象上,我定义了一些Notify*()
方法,这些方法将通过libev
发送异步事件以通过回调获取。
我需要能够在两个对象/线程之间进行通信,但我不确定如何安全地执行此操作。
实际的设计是让pthread
线程对象直接调用不同的Emit*()
方法,以便QObject可以正确地将信息传播到Qt/QML。如果我需要将信息从Qt/QML发送到pthread
/libev
对象,我调用(从Qt线程)Notify*()
方法。
当读取Accessing QObject Subclasses from Other Threads,它说:
的QObject和所有它的子类不是线程安全的。这包括整个事件传递系统。
但再往它指出:
在另一方面,你可以安全地从你的QThread :: run()的执行情况发出信号,因为信号发射是线程安全的。
所以我的问题是,上面介绍的设计是线程安全的吗?我可以安全地拨打myQObject->EmitMySignal()
,这又会来自pthread
对象内的所有这些内容,这些内容又将调用emit signalMySignal()
?
我认为你应该用'postEvent'来处理这个问题,而不是像这样直接访问'QObject'。 'postEvent'是线程安全的,如果您不想或不能使用正常的信号/插槽连接,则为此目的而设计。 – Resurrection
如上所述,发射信号是线程安全的。但是,成员变量的读值不是线程安全的。因此,如果从多个线程访问它,则需要保护对“_status”的访问。从多个线程调用一个* QObject *方法是容易出错的,所以如果你这样做,我推荐几件事:1.将方法分成“从其他线程调用”和“普通”方法,并且具有*独特的命名约定*这些。 2.以相同的方式划分成员变量,并确保互斥 - 保护对多线程中要使用的成员变量的访问。 3.查看代码! – hyde