2012-09-08 28 views
4

我使用Boost ASIO在C++中編寫ThreadPool類。以下是我迄今所編寫的代碼:使用ASIO的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運行(只是爲了簡單起見,解決根本原因)。以下是輸出,當我運行這個程序在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的值未被打印?

回答

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

我建議使用'std :: unique_ptr'(如果有的話)而不是'std :: auto_ptr',因爲'std :: auto_ptr'已被棄用。 –

+0

@JoachimPileborg:同意,與現代編譯器,你應該更喜歡unique_ptr – nogard

+0

@nogard,你的解決方案工作。愚蠢的是,我無法看清「變量超出範圍」問題! Joachim,std:unique_ptr它是! – Cik

1

好吧,我會第一個承認我不知道助力,更具體地說是從地上的一個洞裏提升:: asio,但是我知道一個關於線程池和工作組的hella-lot 。

線程應該睡覺,直到通知新的工作,但如果他們沒有配置這樣做,他們可能會完成他們的線程處理並退出,一個告訴的跡象表明,這種情況是啓動一個游泳池,在發佈任何作品之前需要休息一段合適的時間,並且如果游泳池線程全部終止,那麼它們沒有正確等待。快速閱讀助推文檔產生了this,它可能與您的問題有關。

在那個筆記上,你有可能從main()入口點的池的析構函數實際上是過早地殺死你的工作人員?我看到join_all,但是stop()給了我意志。如果它的名字意味着會解釋很多。據該站的說明()從文檔撥打:

以實現關機,則應用程序將需要調用 io_service對象的stop()成員函數。這將導致 io_service run()調用盡快返回,放棄 未完成的操作,並且不允許現成處理程序調度爲 。

立即關閉和放棄提及似乎對您目前的狀況非常熟悉。

同樣,我不知道提升:從亞當asio,但我在這我會檢查啓動線程對象的配置。他們可能需要配置如何開始,如何等待等等。網絡上必須有大量使用boost:asio的示例,這些示例涉及配置您在此處描述的內容,即工作組範例。我看到boost :: asio是SO上的一個TON,所以也可能有許多相關或近似相關的問題。

如果沒有任何用處,請隨意降級,如果確實如此,我表示歉意。