私は次のコードを持っています:
class A : public QObject
{
Q_OBJECT
public:
A() : QObject()
{
moveToThread(&t);
t.start();
}
~A()
{
t.quit();
t.wait();
}
void doSomething()
{
QMetaObject::invokeMethod(this,"doSomethingSlot");
}
public slots:
void doSomethingSlot()
{
//do something
emit ready();
}
signals:
void ready();
private:
QThread t;
}
なぜdoSomething
からQMetaObject::invokeMethod
経由で呼び出さなければならないのかという質問。接続タイプに何かがあることは知っています。 誰かがボンネットの下にあるものを説明できますか?
Qt::ConnectionType
を指定していないため、メソッドはQt::AutoConnection
として呼び出されます。つまり、オブジェクトのスレッドアフィニティが現在のスレッドに対するものである場合、メソッドは同期的に呼び出されます(通常の関数呼び出しのように)。 、それ以外の場合は非同期。 「非同期」とは、QEvent
が作成されてメッセージキューにプッシュされ、イベントループがそれに到達したときに処理されることを意味します。
受信者オブジェクトが別のスレッドにある可能性がある場合にQMetaObject::invokeMethod
を使用する理由は、別のスレッドのオブジェクトでスロットを直接呼び出そうとすると、スレッドセーフでないデータにアクセスまたは変更した場合に破損または悪化する可能性があるためです。
私はこのトリックが好きです:
void A:doSomethingSlot()
{
if (thread()!=QThread::currentThread()) {
QMetaObject::invokeMethod(this,"doSomethingSlot", Qt::QueuedConnection);
return;
}
// this is done always in same thread
...
emit ready();
}