简体   繁体   English

从另一个(非qt)线程调用QObject方法的线程安全性?

[英]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.

相关问题 QObject重入和线程安全 - QObject reentrancy and thread safety 调用QObject的函数移动到Qt中的不同线程? - Calling a function of a QObject moved to different thread in Qt? 从QT中的另一个GUI线程调用线程时出现问题 - Problems Calling a Thread from another GUI Thread in QT QObject::~QObject:不能从另一个线程停止定时器 - QObject::~QObject: Timers cannot be stopped from another thread 如何利用Qt使QObject方法线程安全? - How to leverage Qt to make a QObject method thread-safe? 以与非Qt应用程序相同的过程加载Qt应用程序会中断非Qt应用程序的工具提示 - Loading a Qt app in same process as non-Qt app breaks non-Qt app's tooltips QT threads:Getting QObject::startTimer: timers cannot be started from another thread 警告 - QT threads :Getting QObject::startTimer: timers cannot be started from another thread warning QT 和 OpenCV 问题查看 Opencv Mat 上的 QGraphicsView 在不同的线程:: QObject::killTimer: 计时器不能从另一个线程停止 - QT and OpenCV problem viewing Opencv Mat on QGraphicsView in different thread :: QObject::killTimer: Timers cannot be stopped from another thread 调用moveToThread()不会将QObject移动到另一个线程。 - Calling moveToThread() doesn't move QObject to another thread. Qt信号参数线程安全 - Qt signal argument thread safety
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM