2016-06-01 13 views
1

Mainthreadの別のスレッドの関数を呼び出すことはできません。問題なく他のスレッドからシグナルを呼び出すことは許されていますか?このコードがMainWindowにあるとしましょう:QThreadはスレッドセーフです

スレッド→moveTOThread(obj); emit obj-> Signal();


か、これが移動するための方法であるあなたに感謝:

Obj.h 
signals: 
    void testSignal(); 
public slots: 
void Func(); 

    MainWindow.h 
    void testSignal(); 

    MainWindow.cpp 
    thread->moveTOThread(obj); 
    connect(this,SIGNAL(testSignal()),obj,SIGNAL(testSignal())); 
    emit testSignal(); 

    Obj.cpp 
    connect(this,SIGNA(testSignal()),this,SLOT(Func())); 

答えて

0

私はあなたがこれを行う場合に何が起こるかは100%を確認していません。しかし、あなたはまだスレッドの境界を越えている/破っている - おそらく、あなたが呼び出しているスレッドから信号が放出されます。

"呼び出し"オブジェクトのシグナルをあなたの "ターゲット"オブジェクトの信号。しかし、これはちょっと悪いことですが、信号がすぐに放射されてしまいます(おそらくこれがあなたの意図です)。これは直接接続信号に似ています。スレッド間では非常に良い理由がない限り、私は誰も考えることができない)。

しかし、信号を送信するオブジェクトのスロットに信号を接続するだけではどうですか。あなたのスレッドの境界を維持するこの方法?

すぐに別のスレッドの信号を強制的に実行しようとしているようです...あなたのユースケースは何ですか?

+0

私はちょうどobjの関数を何とか呼びたいと思っています。以来、obj-> Func();スレッドセーフではありません私はスレッドセーフな方法を探しています。私はobjからシグナルを出し、obj-constructorのシグナルをSlot Func()に接続する必要があります。どうすればFunc()threadsafeを呼び出すことができますか? – Bob

+0

@Bob 'クラスB 'は別のスレッドに存在するオブジェクトであると仮定すると、'クラスA'の信号を 'クラスB 'のスロットに接続するだけです。 'Class B 'の信号を' Class B'のスロットに接続してから、この信号を呼び出す必要はありません。 – thuga

+0

@Bobうーん...もしあなたが望むなら、誰もあなたを止めることはできません。しかし、それはスレッド境界を壊し、そうするのは安全ではありません。あなたのオブジェクト関数を安全に呼び出すには、シグナルを送信することです...その2行のコードが余分に必要です!接続する1本の線、信号を放射する1本の線(ああ、信号を宣言する必要があります)...それだけです!すべてのこの大騒ぎは消え去る。あるいは、これがオブジェクトのインスタンス化を必要としない何らかの "ヘルパー"関数であれば、それを静的関数にすることができます...あなたのユースケースは何ですか?あなたの機能は何をしていますか? –

2

connectは、接続型である第5引数をとります。 デフォルト値AutoConnectionは、スレッドセーフであるQueuedConnection接続タイプを使用します。接続コールが行われたときにオブジェクトが異なるスレッドにあると仮定します。接続時に同じスレッド内にある場合は、非スレッドセーフDirectConnectionタイプの接続を使用します。

thread safetlyは、制御がイベントループに戻るときに宛先スレッドで呼び出すイベントとしてスロット呼び出しをキューに入れることによって実現されます。

+0

['Qt :: AutoConnection'](http://doc.qt.io/qt-5/qt.html#ConnectionType-enum)を使用すると、シグナルが送信されたときにチェックされます。作成されます。 – thuga

4

はい!信号へのデフォルトの自動接続を使用している限り、任意のスレッドから信号を呼び出すことができます。そのようなスロット/ファンクタは、コンテキストオブジェクトのスレッドで実行されます。例えば、これらのライブラリがQtを使用しない場合でも、サードパーティのライブラリからのコールバックからシグナルを発信することができます。

警告:明示的に直接接続されたスロット/ファンクタは、シグナルが呼び出されたスレッドで実行されます。

+0

別のスレッドから関数を呼び出すためにはどういうことが分かりますか? main-gui-threadの別のスレッドオブジェクトから関数を呼び出すだけではどうですか?私はそこから他のスレッドの関数を呼び出すだけであれば問題はありません。 – Bob

+0

@Bob呼び出す関数がスレッドセーフでない場合、未定義の動作に直面しています。問題は「見える」かもしれませんが、あなたのハードドライブを静かにフォーマットしているかもしれません。 –

+0

Idk私は答えを得ていません。私はプログラムのクラッシュなしに別のスレッドの関数を呼び出すことはできますか?余分なコードがあるときに私はなぜ信号とスロットを使用すべきですか? – Bob

関連する問題