0

いくつかのデータが定義されているqtアプリケーション内にこのクラスがあります。

class TableView:public QWidget 
{
  Q_OBJECT

  public:TableView (QWidget * parent = 0);

  std::vector < float >  arr;

そして、いくつかのクラス関数など。ここで、別のスレッド(おそらくこのクラス内から)にソケットサーバーを追加して、ソケットから何かを受け取ったときにこのクラスのデータにアクセスし、新しいデータを計算して返すことができるようにします。

私が使用したテストでは:

  //defines
  DWORD WINAPI SocketHandler(void* lp);
  DWORD WINAPI starttremeshserver(void* lp);


  CreateThread(0,0,&starttremeshserver, (void*)csock , 0,0);

これは機能します。今、私は簡単でプラットフォームに依存しないものが必要です。私はqtで働いているので、多分qthreadで何か。

したがって、問題は、クラスデータにアクセスできるクラス内に新しいスレッド関数を作成できるかどうかです。ty

4

3 に答える 3

5

Qt は必要なものをすべて提供します。ニーズは次のとおりです。

  1. TableViewクラスのデータ メンバーへのスレッド セーフな (シリアル化された) アクセス。

  2. ネットワーク プリミティブ。

  3. ネットワーク アクセスを別のスレッドに移動する柔軟性。

おそらくネットワークからデータを受信して​​おり、arrメンバーを更新したいと考えています。次のようにします。

  1. QObjectの派生クラスを作成します。Processorこれには、ネットワーク接続をセットアップするスロット (おそらくQTcpServer) があります。QTcpSocket接続時に、データを交換するために使用します。すべてのデータ処理がクラスのスロットで行われていることを確認してください。ベクトルで更新する新しい値がある場合は、emit単にhasFloat(int,float).

  2. setFloat(int,float)にスロットを追加しTableViewます。

  3. setFloatのインスタンスからの信号を に接続ProcessorしますTableView

この時点で、すべてが GUI スレッドで実行されますが、ネットワーク データを待機しないため、コードはノンブロッキングです。QTcpServerとによって発せられた信号に応答しますQTcpSocket。必要に応じて、そのままにしておくことができます。

Processorベンチマークでメインスレッドが CPU バウンドであることが示されている場合、クラスを別のスレッドで実行するのは簡単です。

int main(int argc, char** argv) {
   bool separateThread = true;
   QApplication app(argc, argv);
   TableView view;
   Processor proc;
   connect(&proc, SIGNAL(hasFloat(int,float)), &view, SLOT(setFloat(int,float)));
   QThread thread;
   if (separateThread) {
      thread.start();
      proc.moveToThread(&thread);
   }
   view.show();
   const bool rc = app.exec();
   if (thread.isRunning()) {
      thread.exit(); // tells the event loop in the thread to bail out
      thread.wait(); // waits for the above to finish
   }
   return rc;
}

スレッド全体に物事を広げると、どういうわけか魔法のようにスレッドが良くなるという誤解があります。スレッドは、実行中の計算の CPU バウンドとブロック API という特定の問題に対するソリューションです。処理が些細なものであれば、CPU バウンドになる可能性は低くなります。Qt はノンブロッキングの非同期ネットワーキングを提供します。したがって、通常、2 番目のスレッドをスピンする必要はまったくありません。

そうでないことを示すには、最初に実数を表示する必要があります。それ以外の場合は、スレッド化のカーゴ カルトに参加しています: ああ、それはネットワークです。別のスレッドに移動する必要があります。いいえ、必ずしもそうではありません。最初に測定します。あなたがしていることを理解してください。

上記のコードのスレッド セーフの理由は次のとおりです。Processorインスタンスを別のスレッドに移動すると、Qt はタイプを使用してすべてのシグナルスロット接続を再接続しQt::QueuedConnectionます。したがって、 がProcessor出力されると、内部的に、存在するスレッド (この場合は GUI スレッド)hasFloatのイベント キューにイベントがキューイングされます。TableViewイベント ループがスピンすると (ここでは、アプリケーションのイベント ループになります)、イベントを取得して への呼び出しを実行しますTableView::setFloat。これにより、arrデータ メンバーへのアクセスがシリアル化され、複数のスレッドから同時にアクセスされる可能性がなくなります。

于 2012-06-04T13:52:09.417 に答える
1

Qt は、ここにあるようにスレッドをサポートしています

スレッドとデータへのアクセスに加えて、スレッドセーフ コードの同期が必要になります。これは Linux では pthread ミューテックスと呼ばれ、Qt ではここで説明したように QMutex と呼ばれます。

Qt ネットワーキング プリミティブはこちらにあります

これらのスレッド化およびネットワーク プリミティブの Qt 実装を使用すると移植性が高くなるため、Windows でも機能するはずです。

そのクラスのデータにアクセスするクラスからスレッド関数を作成することについての質問については、答えはイエスです。スレッド関数を作成する代わりに、スレッド オブジェクト、つまり QThread を作成することをお勧めします。スレッド オブジェクトを作成するときは、そのクラスのインスタンスへの参照を渡す必要があります。これにより、スレッドはクラス インスタンスにアクセスできるようになります。

于 2012-06-04T09:10:21.073 に答える
1

<thread>個人的には、C++ 11 で使用できるスレッドのために、おそらくブーストに基づく、より高レベルのソケット サポートを探します。

特定の質問に答えるには:

class Foo
{
private:
    void spinthread()
    {
        thread t([this] { 
            this->bar = 12;
        });
    } 

private:
   int bar;
}

Win32 スレッド API を使用している場合、スレッド プロシージャには、CreateThread 呼び出し中にインスタンスを渡すために使用できるパラメーターがあります。

于 2012-06-04T09:11:20.013 に答える