問題タブ [qeventloop]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
multithreading - Qt のマルチスレッドとイベント ループについて
Qt マルチスレッドと Qt 4.8 でのイベント ループを理解するのに役立つ説明を探しています。また、私は一般的にスレッド化が初めてなので、それが私の問題の一部であると付け加えます。
私の現在の状況は、QTMultiMedia-QAudioOutput を使用して頻繁にサウンドを再生する必要がある Qt アプリを持っていることです。MainGuiとAudioWorkerの 2 つのクラスがあります。AudioWorker を呼び出してサウンドを "play()" したいことがよくあります。
サウンドが再生される前にプロセスが終了しないように、どうやら QAudioOutput にはイベント ループが必要です。したがって、スレッドが役立つことを理解しています。
スレッドを正しく理解していれば、生成されたスレッドは、何らかの方法で切り離されない限り、それを作成した関数よりも長く生きることはできませんか? MainGui クラスでサウンドを再生する通知を受信し、AudioWorker で play() を呼び出すスロット接続を介して新しいスレッドを生成した場合、MainGui 通知関数が終了すると、イベント ループを持つスレッドが終了することはありませんか? これが事実である場合、どちらにしても MainGui はイベント ループを必要とするでしょうか?
確かに私は何かが欠けていますか?どうにかしてスレッドをデタッチする必要がありますか?デタッチに関する Qt ドキュメントにはあまり記載されていません。単純な音を鳴らすためだけに、このプロセス全体が過剰に思えます。
更新しました
play() 関数で QThread を作成することで問題を解決しました。スレッドは、シグナルを送信するまで途中で終了しません。
https://nachtimwald.com/2015/05/02/effective-threading-using-qt/で、隠れているが素晴らしい例を見つけました。
c++ - Qthread deleteLater() プログラムのクラッシュ
QT 4.8: セグメント フォールトと I/O の可能性のあるエラーがコードに多数表示されますが、それらを理解することはできません。print ステートメントから、多くの奇妙で一貫性のない動作を見てきました。これは、おそらく競合状態を示しています。多くの場合、すべてが完璧に機能します。ワーカー デストラクタが呼び出された直後に、メイン接続の deleteLater() の問題を示す I/O エラーが発生することがあります。また、デストラクタで audioOutput を削除しようとすると、何度も機能し、他の試みでデストラクタの途中でランダムにセグメント障害 (または I/O) が発生します。私の問題は、worker cleanup/ connect quit()/deletelater() 呼び出しの 2 つと、毎回独自のイベント ループを作成する必要がある worker の再帰ループに起因する可能性があるため、以前の呼び出しが行われる前に終了信号を発する可能性があると考えています。掃除した?
具体的には、私の質問は次のとおりです。
deleteLater() が I/O の可能性のあるエラーを作成する原因は何ですか?
ワーカークラス内のポインターを削除して、正しい時間(終了)に削除するにはどうすればよいですか?またはQTがこれを処理しますか?
Gui と .h
ワーカー クラスと .h
更新しました:
まだ断続的な問題がありますが、次の行をコメントアウトすると、quit=true の設定と組み合わせていくつかの問題を解決できました。
しかし、これはメモリリークを引き起こす可能性がありますか?
更新 2:
ここで独り言を言っていると思い始めていますが、わかったと思います。これは、ワーカが finished() を発行すると、オープン ループを閉じる quit() シグナルからアンワインドする時間が原因で、ワーカが実際に終了する前にスレッドが finished() を返していたため、タイミングの問題であったようです。そのため、閉じたループごとにワーカーからカスタム シグナルを発行し、これをメインで追跡します。期待どおりの結果を受け取ったら、wait() を解放し、スレッドを削除してからワーカーを削除します。これが正しいかどうかはわかりませんが、機能しているようです。私にはハックのように思えますが、IMO ワーカーが終了するまでスレッドは終了してはならず、無意味に思えます。でもまあ。