[英]Thread safety of calling QObject's method from another (non-qt) thread?
我有兩個對象,它們存在於不同的線程中,我試圖確定使用的模式是否是線程安全的。
第一個對象是QObject派生的並且在主Qt線程中存在(在其中創建)。 該類包含一些應該從QML調用的Q_INVOKABLE
方法,一些定義為signals:
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*()
方法。
從其他線程讀取訪問QObject子類時 ,它說:
QObject及其所有子類都不是線程安全的。 這包括整個事件傳遞系統。
但隨后進一步說明:
另一方面,您可以安全地從QThread :: run()實現中發出信號,因為信號發射是線程安全的。
所以我的問題是,上面描述的設計是線程安全的嗎? 我可以安全地調用myQObject->EmitMySignal()
,它會從pthread
對象內部調用emit signalMySignal()
嗎?
我將演示如何用事件而不是你不能使用的信號和插槽來實現你想要的東西(因為一方不是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;
}
};
在你的另一個主題中你會這樣做:
MyObjectClass *p; //holds pointer to the instance in main thread
qApp->postEvent(p, new QEvent(QEvent::User+1));
這將檢索指向存在於主線程中的應用程序的指針,並將事件發布到其事件循環中。 事件將從調用異步處理,但行為將與您現在所做的不同。 但它會更安全,更優雅。 您可以根據需要添加任意數量的類型。 如果您沒有處理它,請不要忘記將事件傳播給父級!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.