為什么要使用ACE_Task來管理線程
從C#轉到C++后,感覺到C++比C#最難的地方,就是在系統編程時,C#中有對應的類庫,我接觸到一個類后,就可以通過這個類,知道很多相關的功能。而在C++中,必須使用Windows API,但是Windows API的缺點反而是不系統。比如,想要創建一個線程時,C#中可以通過新建一個Thread類,我得到這個類后,就可以通過幫助或者MSDN了解到這個類中有哪些方法,如何管理線程等。但是C++中,創建一個線程,需要調用CreateThread,但因為它是一個API,所以很難快速的了解到與線程管理相關的API,至少對我來說,這是一個難點。
C#的優勢是以類的方式去管理線程,而C++ 調用API更像是在單打獨斗,顯得特別特別散亂。
那么在C++中,我們能不能以類的方式去管理線程呢。針對這個問題,ACE_Task便浮出了水面。
ACE_Task使用方法
ACE_Task對常用線程處理進行了OO包裝,通過ACE_Task,能對線程進行更好的操作。
根據ACE_Task的父類ACE_Task_Base中的注釋,可以總結出以下幾點:
- 想要使用ACE_Task,就要從ACE_Task派生一個子類,然后實現比較重要的幾個虛方法。
- 實現服務初始化和終止方法:open()方法應該包含所有專屬於任務的初始化代碼。其中可能包括諸如連接控制塊、鎖和內存這樣的資源。close() 方法是相應的終止方法。
- 調用啟用(Activation )方法:在主動對象實例化后,你必須通過調用activate()啟用它。要在主動對象中創建的線程的數目,以及其他一些參數,被傳遞給activate()方法。activate()方法會使svc()方法成為所有它生成的線程的啟動點。
- 實現服務專有的處理方法:如上面所提到的,在主動對象被啟用后,各個新線程在svc()方法中啟動。應用開發者必須在子類中定義此方法。
編寫ACE_Task的Demo
下面就通過總結的幾點來編寫一個Demo
首先是派生ACE_Task的子類ShowTask
#pragma once #include "ace/Task_T.h" #include <string> #include <iostream> using namespace std; class ShowTask : public ACE_Task<ACE_SYNCH> { public: ShowTask(const char* str_to_show, int interval) : show_str_(str_to_show), interval_(interval) { //啟動線程 activate(); } ~ShowTask() { //結束線程 close(); } public: virtual int open( void *args = 0 ) { cout << "線程啟動" << endl; return 0; } virtual int close( u_long flags = 0 ) { cout << "線程結束" << endl; return 0; } virtual int svc( void ) { int time_begin = GetTickCount(); while(true) { int time_end = GetTickCount(); if(time_end - time_begin >= interval_) { time_begin = time_end; cout << show_str_ << endl; } Sleep(10); } return 0; } private: //需要顯示的信息 string show_str_; //間隔多長時間進行顯示 int interval_; };
然后在程序中調用ShowTask
#include "ShowTask.h" int _tmain(int argc, _TCHAR* argv[]) { ACE::init(); string str = "這是一個測試程序"; ShowTask task(str.c_str(), 1000); Sleep(10000); ACE::fini(); return 0; }
運行效果圖:
需要注意的地方
在程序中使用ACE_Task,那么就必須在使用前對ACE進行初始化,即調用ACE::init方法,然后在程序結束的時候調用ACE::fini方法。如果沒有進行初始化就調用ShowTask,那么程序就會崩潰。
至於為什么會崩潰,以及ACE::init方法做了些什么,后續的文章中會詳細的介紹。
關於open方法的疑惑
從上面的測試圖中可以看到,線程結束后,調用了close方法,但是在線程啟動時並沒有調用open方法。
而且從谷歌找到的資料中也介紹,在線程啟動的時候回調用open方法,而且他們的示例程序與本文中提供的demo中關於ACE_Task的使用方法也基本一致。
那么open方法為什么沒有被調用呢,究竟是使用方法不對,還是因為ACE版本不同導致的。關於這個問題也會在后續的文章中進行詳細的介紹。