0

私はたくさんのメソッドを持つエンコーダークラスを持っています。これは Qthread のサブクラスです。私はマルチスレッドが初めてで、

このクラスがどのようにメソッドをスレッド化しているかを理解しようとしています

... qthread のサブクラスになければならないメソッドをスレッド化することを理解しています。これを実行すると、このクラスのスレッド化されたコードが実装されます。そして、スレッドは、このクラスのオブジェクトで start メソッドが呼び出されたときにのみ開始されます。

質問: まず、この実行の実装から何を推測しますか?

void Encoder::run(void)
{
    VERBOSE(VB_DEBUG, "Encoder::run");

    if (WILL_PRINT(VB_DEBUG))
        print_stats_timer_id = QObject::startTimer(kEncoderDebugInterval);
    health_check_timer_id = QObject::startTimer(kEncoderHealthCheckInterval);

    if (init())
        exec();
    else
        VERBOSE(VB_ERROR, "Encoder::run -- failed to initialize encoder");

    QObject::killTimer(health_check_timer_id);
    if (print_stats_timer_id)
        QObject::killTimer(print_stats_timer_id);

    cleanup();
}

質問:スレッド コンテキストとは、そのメソッドに関連して何を意味しますか。

また

質問:このクラスのスレッドが開始される前に、このクラスのメソッドが呼び出された場合はどうなりますか?

4

1 に答える 1

4
  1. あなたが書いたクラスは、スレッドを作成し、QObject::timer を初期化します。次に、ユーザー定義の init() 関数を呼び出し、次にQThread::exec()関数を呼び出します。

    1. 私の推測では、あなたは exec() が実際の作業が行われるユーザー定義関数になることを意図していたのでしょう。QThread::exec() がスレッドの Qt イベント キューを処理することに注意してください。
    2. また、一部のプラットフォームでは、「スレッドからタイマーを作成中にエラーが発生しました」という警告メッセージが表示される場合があります。Linuxでコードが正常に実行されたときに、Windowsでこのエラーが発生しました
    3. また、スレッド内からQThread::exec() 関数またはQApplication::processEvents()を呼び出さない場合、タイマーは決して発生しないことに注意してください。
  2. Qt のスレッド コンテキストは、他のスレッドの概念と同じです。つまり、すべてのメモリがスレッド コード間で共有されます (この時点で "run()" 関数に入力されます)。そして、あなたのオブジェクトを呼び出す他のコンテキスト。このオブジェクトがスレッドで実行され、スレッドの外部からアクセスされる可能性がある場合は、共有データを保護する必要があります。

  3. すべてのデータはスレッド コンテキスト間で共有されるため (これは共有メモリ マルチプロセッシング モデルです)、スレッド実行前/後/実行中に関数を呼び出すことに問題はありません。とすれば:
    1. オブジェクトは、メソッドを呼び出す前に完全に構​​築されます。オブジェクトがスレッドで作成されない限り、これは必ずしもスレッドにとって特別なことではありません。
    2. すべてのデータ メンバーはミューテックス ロックで保護されます (これについては #2 でわかりませんでした)。QMutexLockerは、Qt でミューテックス ロックを処理する便利なスタック ベースの RAII 方法です。

ここであなたの質問に完全に答えたと思うので、参考のために、別のサイトに書いたRAIIスレッドの記事にリンクします。

編集:スレッドシナリオに関する特異性:

class MyThreadedClass : public QThread
{
  MyThreadClass(const boost::shared_ptr<SomeOtherClass> &t_object)
    : m_object(t_object) {}

  void doSomething()
  {
    // Depending on how this method was called (from main, from internal thread)
    // will determine which thread this runs on, potentially complicating thread
    // safety issues.
    m_object->someThing(); 
  }

  void run()
  {
    // I'm now in a thread!
    m_object->someFunction(); // oops! The call to someFunction is occurring from 
                              // a thread, this means that SomeOtherClass must be 
                              // threadsafe with mutex guards around shared 
                              // (object level) data.
    // do some other stuff
  }
};

int main()
{
  MyThreadClass thread(someobjectfromsomewhere);
  thread.start(); // MyThreadClass is now running
  thread.doSomething(); // The call to doSomething occurs from main's thread.
                        // This means 2 threads are using "thread", main 
                        // and "thread"'s thread. 
  // The call to thread.doSomething hits Thread.m_object, which means that 
  // now multiple threads are also accessing m_object ("thread" and "main").
  // This can all get very messy very quickly. It's best to tightly control 
  // how many threads are hitting an object, and how
}
  • 注: QFutureを調査することをお勧めします。これは、エンコーダーなどのこの種の非同期タスクを処理するように設計されており、 QFuture を使用すると、共有データとデッドロックの潜在的なスレッド化の問題が回避されます。
于 2011-03-09T15:15:39.130 に答える