【问题标题】:ThreadPool using ASIO - Threads Exit, Task not performed使用 ASIO 的 ThreadPool - 线程退出,未执行任务
【发布时间】:2012-09-08 08:53:50
【问题描述】:

我正在使用 Boost ASIO 用 C++ 编写一个 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 运行(只是为了让事情在这里简单并找到根本原因)。以下是我在 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]

我有两个问题:

  1. 为什么我的线程正在退出,即使我正在发帖 while 循环中的任务?
  2. 为什么是 JobClass 的输出,即变量 a、b 的值 并且 c 没有被打印出来?

【问题讨论】:

    标签: c++ multithreading boost boost-asio


    【解决方案1】:

    我认为这是因为您在 CreateThreadPool 方法中创建了工作对象,该方法在超出范围时会自动销毁 -> 在这种情况下 io_service 没有活动的工作并且不处理您的任务。

    尝试使您的 ThreadPool 类的“工作”实例变量,而不是方法中的本地变量。

    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));
        }
    }
    

    【讨论】:

    • 我建议使用std::unique_ptr(如果有的话)而不是std::auto_ptr,因为std::auto_ptr 已被弃用。
    • @JoachimPileborg:同意,对于现代编译器,您应该更喜欢 unique_ptr
    • @nogard,您的解决方案有效。愚蠢的是我无法看穿“变量超出范围”的问题!约阿希姆,std:unique_ptr 是!!
    【解决方案2】:

    好吧,我会第一个承认我不知道 boost,更具体地说是从地里的一个洞里 boost::asio,但我知道很多关于线程池和工作人员的知识。

    线程应该休眠直到收到新工作的通知,但如果它们没有配置为这样做,它们可能只会完成线程进程并退出,这是这种情况的一个明显迹象是启动一个池,在发布任何工作之前睡眠一段合理的时间,如果池线程都终止,它们没有正确等待。快速阅读 boost 文档得到了this,它可能与您的问题有关。

    关于这一点,是否有可能从 main() 入口点对池进行析构函数实际上过早地杀死了您的工作人员?我看到了 join_all,但是那个 stop() 给了我威力。如果它做到了它的名字所暗示的那样,那将解释很多。根据文档中对 stop() 调用的描述:

    为了实现关机,应用程序需要调用 io_service 对象的 stop() 成员函数。这将导致 io_service run() 调用尽快返回,放弃 未完成的操作,并且不允许准备好的处理程序 已发送。

    您当前的情况似乎对立即关闭和放弃的提及非常熟悉。

    同样,我不知道来自 Adam 的 boost:asio,但如果我这样做,我会检查 boost 线程对象的启动配置。他们可能需要配置如何启动、如何等待等。在网络上必须有大量使用 boost:asio 的示例,这些示例涉及配置您在此处描述的内容,即工作组范式。我在 SO 上看到 boost::asio 一个 TON,因此可能还有许多相关或接近相关的问题。

    如果没有任何用处,请随时降级,如果是这样,我深表歉意。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-13
      • 2017-04-28
      • 1970-01-01
      • 2012-05-02
      • 2012-11-08
      • 1970-01-01
      • 1970-01-01
      • 2020-07-08
      相关资源
      最近更新 更多