0

私のプログラムが何をしていたのか、何を変更しようとしているのかを説明しようとします:

クラス MainWindow のメインスレッドからボタンクリックで実行されるこの関数がありました: public QMainWindow :

関数は次のようになり、別のファイル内で指定されます。

void MakeMeshStructure(MeshStructureLayers layers,
                      Handle_AIS_InteractiveContext theContext,
                      Handle_TDocStd_Document aDoc,
                      MyMesh &mesh,
                      int detail_vertex,
                      double insulation_thickness,
                      OpenMesh::VPropHandleT<MyMesh::Scalar> _max_beam_offset);
}

メッシュで機能し、メッシュのすべての頂点、面、エッジのジオメトリを作成します。このジオメトリは、Context で表示されます。このプロセスには非常に時間がかかり (30 分)、GUI がブロックされます。

私がやりたいことは、QThread::idealThreadCount() と同じ数のスレッドを持ち、計算時に GUI を解放して高速化することです。(これは正しい考えですか?)

メッシュを等分に分割し、この範囲の頂点を関数 (上記) に渡して、別のトレッドの 1 つの頂点範囲のみを操作したいと考えています。

このデータをどのように渡し、スレッドセーフにするかを理解するのに問題があります。私はその多くのコードを知っていますが、これを解決するための私の試みは次のとおりです。

http://pastebin.com/u/mzagar

問題は、すべてのデータを正しい方法で取得し、スレッドを機能させることです。どこでミューテックスを使用する必要がありますか。メインスレッドによるスレッド作業時に書き込むことができるすべてのデータについて? 非常に混乱。タイ

編集:

コードを編集しました: http://pastebin.com/u/mzagar 構造体 cadData を作成してデータを渡しました。これは私がスレッドを開始する方法です:

connect(this, SIGNAL(startMake1(cadData)), cThreads.at(0), SLOT(MakeMesh(cadData)));
//...
cThreads.at(0)->moveToThread(threads.at(0));
//...
threads.at(0)->start();
 //...
emit startMake1(aCadDatas.at(0));
 //...

問題は、スレッドが同時に機能していないように見え、GUI がフリーズすることです。プロセスは次のようになります。

  • GUI がフリーズする
  • スレッド 1 の処理
  • スレッド 1 の処理がやり直されます
  • スレッド 2 の処理
  • スレッド 2 の処理が再び行われます
  • ...
  • GUI がフリーズしない

理由はありますか?

編集2:

これをクラス コンストラクターに移動して、同じスレッドの複数回の実行を削除しました。

connect(this, SIGNAL(startMake1(cadData)), cThreads.at(0), SLOT(MakeMesh(cadData)));
//...
cThreads.at(0)->moveToThread(threads.at(0));
//...
threads.at(0)->start();
4

2 に答える 2

2

QThread を使用しているため、Qt のスレッドセーフなスロットとシグナルのメカニズムを使用して作業を行うことで、ミューテックスなどの明示的な使用を回避できる可能性があります。基本的に、スレッドに送信する必要があるデータをオブジェクトにパッケージ化し、そのオブジェクトを引数として持つシグナルを発行します。スレッドは、そのオブジェクトのコピーをスロット (以前にシグナルに接続したもの) で受け取り、データの使用を開始します。ワーカー スレッドからメイン スレッドにデータを戻すには、同じことを逆に繰り返します。 これは、いくつかのサンプルコードを含む記事です。

于 2012-06-25T19:54:31.787 に答える
0

ジェレミーの答えに追加するには:シグナルスロットメカニズムを使用する代わりに、QObject間でイベントを送信することで同じことができます。最も便利な方を使用してください。

重要なのは、Qt のビルトイン イベント ループ ミューテックスを活用することです。送信者とは異なるスレッドに存在するオブジェクトにシグナルを送信すると、シグナルは QMetaCallEvent に変換され、受信側 QObject のイベント キューにポストされます。もちろん、これはスレッドセーフな方法で行われ、それを活用するだけで済みます。明示的なイベントの送信も同じように機能します。レシーバーが存在するスレッドで回転するイベント ループは、単に QMetaCallEvents を取得し、それに応じてスロット呼び出しを実行するか、customEvent()メソッドの実装にイベントをディスパッチします。

raw を開始すると、メソッドQThreadのデフォルトの実装によってイベント ループが開始されます。run()このようなスレッドは事実上アイドル状態であり、CPU リソースをまったく消費していないことに気付くでしょう。イベント キューは空であり、イベント ループはブロックされ、誰かがそのキューにイベントを投稿するのを待っています。いくつかの QObject をそのようなスレッドに移動すると、キューに入れられたシグナルスロットの配信がそのスレッドのイベント ループを介して行われます。GUIスレッドであろうと他のスレッドであろうと、同じように機能します。イベントやキューに入れられたシグナルの受信に関しては、GUI スレッドは決して特別なものではありません。

于 2016-08-10T20:56:57.497 に答える