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

时间:2016-12-01 17:10:20

标签: c++ multithreading qt

我有两个对象,它们存在于不同的线程中,我试图确定使用的模式是否是线程安全的。

第一个对象是QObject派生的,并且在主Qt线程中存在(在其中创建)。该类包含一些应该从QML调用的Q_INVOKABLE方法,一些signal*()方法定义为signals:和一些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()emit signalMySignal()将从pthread对象内拨打function readFileAsync(file) { var p = $q.defer(); var reader = new FileReader(); reader.onload = function(event) { console.log('[FileReader] Success in read ' + JSON.stringify(event)); //var byteFile = new Int8Array(event.target.result); //p.resolve(byteFile); p.resolve(event.target.result); }; reader.onabort = function(reason) { console.log('[FileReader] abort ' + JSON.stringify(reason)); p.reject(reason); reader.abort(); } reader.onerror = function(err) { console.log('[FileReader] ' + JSON.stringify(err)); p.reject(err); }; // for ios var localFileURL = file.fullPath.indexOf('file:/') == 0 ? file.fullPath : 'file://' + file.fullPath; window.resolveLocalFileSystemURL(localFileURL, function (fileEntry) { fileEntry.file(function (validFile) { reader.readAsArrayBuffer(validFile); }); }); return p.promise; } 所有这些内容?

1 个答案:

答案 0 :(得分:0)

我将演示如何使用事件而不是您无法使用的信号和插槽来实现您想要的功能(因为一方不是DELIMITER '|'派生的)

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;
    }
};

这将检索指向位于主线程中的应用程序的指针,并将事件发布到其事件循环中。事件将从调用异步处理,但行为将与您现在所做的不同。但它会更安全,更优雅。您可以根据需要添加任意数量的类型。如果您还没有处理它,请不要忘记将事件传播给父级!