4

Boost ASIO を使用して C++ で ThreadPool クラスを作成しています。これまでに書いたコードは次のとおりです。

ThreadPool クラス

    using namespace std;
    using namespace boost;

    class ThreadPoolClass {
    private:

        /* The limit to the maximum number of threads to be
         * instantiated within this pool 
         */
        int maxThreads; 
        /* Group of threads in the Pool */
        thread_group threadPool;

        asio::io_service asyncIOService;

        void _Init()
        {
            maxThreads = 0;
        }
    public:
        ThreadPoolClass();
        ThreadPoolClass(int maxNumThreads);
        ThreadPoolClass(const ThreadPoolClass& orig);
        void CreateThreadPool();
        void RunTask(JobClass * aJob);
        virtual ~ThreadPoolClass();

    };
    ThreadPoolClass::ThreadPoolClass() {
    _Init();
    }



ThreadPoolClass::ThreadPoolClass(int maxNumThreads) {
    _Init();
    maxThreads = maxNumThreads;
}

void ThreadPoolClass::CreateThreadPool() {

    asio::io_service::work work(asyncIOService);

    for (int i = 0; i < maxThreads; i++) {
        cout<<"Pushed"<<endl;
        threadPool.create_thread(bind(&asio::io_service::run, &asyncIOService));
    }
}

void ThreadPoolClass::RunTask(JobClass * aJob) {
    cout<<"RunTask"<<endl;
    asyncIOService.post(bind(&JobClass::Run,aJob));
}

ThreadPoolClass::ThreadPoolClass(const ThreadPoolClass& orig) {
}

ThreadPoolClass::~ThreadPoolClass() {
    cout<<"Kill ye all"<<endl;
    asyncIOService.stop();
    threadPool.join_all();
}

ジョブクラス

using namespace std;

class JobClass {
private:
    int a;
    int b;
    int c;

public:

    JobClass() {
        //Empty Constructor
    }

    JobClass(int val) {
        a = val;
        b = val - 1;
        c = val + 1;
    }

    void Run()
    {
        cout<<"a: "<<a<<endl;
        cout<<"b: "<<b<<endl;
        cout<<"c: "<<c<<endl;
    }

};

主要

using namespace std;

int main(int argc, char** argv) {

    ThreadPoolClass ccThrPool(20);
    ccThrPool.CreateThreadPool();
    JobClass ccJob(10);
    cout << "Starting..." << endl;
    while(1)
    {
        ccThrPool.RunTask(&ccJob);
    }
    return 0;
}

したがって、基本的には 20 個のスレッドを作成していますが、現在は ioservice によって実行される (同じ) タスクを 1 つだけ投稿しています (ここでは単純にして根本的な原因を突き止めるためです)。このプログラムを GDB で実行したときの出力は次のとおりです。

Pushed
[New Thread 0xb7cd2b40 (LWP 15809)]
Pushed
[New Thread 0xb74d1b40 (LWP 15810)]
Pushed
[New Thread 0xb68ffb40 (LWP 15811)]
Pushed
[New Thread 0xb60feb40 (LWP 15812)]
Pushed
[New Thread 0xb56fdb40 (LWP 15813)]
Pushed
[New Thread 0xb4efcb40 (LWP 15814)]
Pushed
[New Thread 0xb44ffb40 (LWP 15815)]
Pushed
[New Thread 0xb3affb40 (LWP 15816)]
Pushed
[New Thread 0xb30ffb40 (LWP 15817)]
Pushed
[New Thread 0xb28feb40 (LWP 15818)]
Pushed
[New Thread 0xb20fdb40 (LWP 15819)]
Pushed
[New Thread 0xb18fcb40 (LWP 15820)]
Pushed
[New Thread 0xb10fbb40 (LWP 15821)]
Pushed
[New Thread 0xb08fab40 (LWP 15822)]
Pushed
[New Thread 0xb00f9b40 (LWP 15823)]
Pushed
[New Thread 0xaf8f8b40 (LWP 15824)]
Pushed
[New Thread 0xaf0f7b40 (LWP 15825)]
Pushed
[New Thread 0xae8f6b40 (LWP 15826)]
Pushed
[New Thread 0xae0f5b40 (LWP 15827)]
Pushed
[New Thread 0xad8f4b40 (LWP 15828)]
Starting...
RunTask
Kill ye all
[Thread 0xb4efcb40 (LWP 15814) exited]
[Thread 0xb30ffb40 (LWP 15817) exited]
[Thread 0xaf8f8b40 (LWP 15824) exited]
[Thread 0xae8f6b40 (LWP 15826) exited]
[Thread 0xae0f5b40 (LWP 15827) exited]
[Thread 0xaf0f7b40 (LWP 15825) exited]
[Thread 0xb56fdb40 (LWP 15813) exited]
[Thread 0xb18fcb40 (LWP 15820) exited]
[Thread 0xb10fbb40 (LWP 15821) exited]
[Thread 0xb20fdb40 (LWP 15819) exited]
[Thread 0xad8f4b40 (LWP 15828) exited]
[Thread 0xb3affb40 (LWP 15816) exited]
[Thread 0xb7cd2b40 (LWP 15809) exited]
[Thread 0xb60feb40 (LWP 15812) exited]
[Thread 0xb08fab40 (LWP 15822) exited]
[Thread 0xb68ffb40 (LWP 15811) exited]
[Thread 0xb74d1b40 (LWP 15810) exited]
[Thread 0xb28feb40 (LWP 15818) exited]
[Thread 0xb00f9b40 (LWP 15823) exited]
[Thread 0xb44ffb40 (LWP 15815) exited]
[Inferior 1 (process 15808) exited normally]

2 つの質問があります。

  1. while ループでタスクを投稿している場合でも、スレッドが終了するのはなぜですか?
  2. JobClass からの出力、つまり変数 a、b、c の値が出力されないのはなぜですか?
4

2 に答える 2

3

これは、スコープ外になると自動的に破棄される CreateThreadPool メソッドで作業オブジェクトを作成するために発生すると思います。この場合、io_service にはアクティブな作業がなく、タスクを処理しません。

メソッド内のローカル変数ではなく、ThreadPool クラスの 'work' インスタンス変数を作成してみてください。

class ThreadPoolClass {
private:

    thread_group threadPool;

    asio::io_service asyncIOService;

    std::auto_ptr<asio::io_service::work> work_;

public:
};



ThreadPoolClass::ThreadPoolClass(int maxNumThreads) {
    _Init();
    maxThreads = maxNumThreads;
}

void ThreadPoolClass::CreateThreadPool() {

    work_.reset(new asio::io_service::work(asyncIOService));

    for (int i = 0; i < maxThreads; i++) {
        cout<<"Pushed"<<endl;
        threadPool.create_thread(bind(&asio::io_service::run, &asyncIOService));
    }
}
于 2012-09-08T11:43:08.857 に答える
1

わかりました、私はブーストを知らないことを最初に認めます。より具体的には、地面の穴からのブースト::asioですが、スレッドプールと作業員についてはかなり知っています。

スレッドは、新しい作業が通知されるまでスリープするはずですが、そうするように構成されていない場合は、スレッド proc を終了して終了する可能性があります。作業を投稿する前に妥当な時間、およびプールスレッドがすべて終了している場合、それらは適切に待機していません。ブーストドキュメントをすばやく読んだところ、これが得られました。これは、問題に関連している可能性があります。

その点で、 main() エントリ ポイントからのプールのデストラクタが、実際に作業員を時期尚早に殺している可能性はありますか? join_all が表示されますが、その stop() はウィリーを提供します。それがその名前が意味することをするなら、それは多くを説明するでしょう. ドキュメントからの stop() 呼び出しの説明によると:

シャットダウンを行うには、アプリケーションは io_service オブジェクトの stop() メンバー関数を呼び出す必要があります。これにより、io_service run() 呼び出しができるだけ早く返され、未完了の操作が破棄され、準備完了ハンドラーのディスパッチが許可されなくなります。

その即時のシャットダウンと放棄の言及は、あなたの現在の状況に疑わしいほど馴染みがあるようです。

繰り返しますが、私は Adam の boost:asio については知りませんが、これについては、ブースト スレッド オブジェクトのスタートアップ コンフィギュレーションを確認します。開始方法、待機方法などの構成が必要になる可能性があります。ここで説明しているまさにその構成、つまり作業員のパラダイムに関して、ウェブ上でboost:asioを使用するサンプルが多数あるはずです。boost::asio が SO の TON であることがわかります。そのため、関連する、または関連する質問が多数ある可能性があります。

役に立たない場合はお気軽にダウングレードしてください。その場合はお詫び申し上げます。

于 2012-09-08T09:21:35.367 に答える