Symbian學習筆記(6)——關(guān)于多線程與活動對象
既然如此,那我們就不說“多線程”,說說“多任務(wù)”吧,活動對象(Active Object)提供了非搶占式的多任務(wù)協(xié)同處理機制,它不是多線程的,而是運行在一個單線程中。
AO機制包括兩個類CActiveScheduler和CActive:
調(diào)度器CActiveScheduler:顧名思義它是協(xié)調(diào)多個活動對象的調(diào)度者。既然是非搶占式的,那它的調(diào)度原則是什么呢?教材上說法是:
A) 根據(jù)活動對象的優(yōu)先級順序?qū)σ炎缘乃谢顒訉ο笾饌€檢查。
B) 判斷它是否是活動的(IsActive),且它的iStatus是否不為KRequestPending。
C) 滿足則執(zhí)行它的RunL方法。
活動對象CActive:這可以理解為一個“線程”,就象Java中的Runable。它受調(diào)度器的指揮,它的關(guān)鍵在于類型為TRequestStatus的iStatus成員變量。
一般情況下在CActive中會有一個異步操作(方法形參表中包括一個TReuqestStatus類型參數(shù)),如果沒有也無所謂(根據(jù)上面的調(diào)度原則,只要保證它不為KRequestPending即可)。
因為GUI應(yīng)用自帶了CActiveScheduler,所以我們要做的事情就是實現(xiàn)一個派生于CActive的子類,重載方法RunL()、DoCancel()和RunError()。當然還應(yīng)該有一個類似于Start的方法來啟動它。
Start負責啟動,一般是在這里去執(zhí)行一個異步操作(比如加載JPEG的圖像,如上篇所言;或者打開一個定時器,如書上例子)。如果沒有異步操作的話,也可以在這里啥事都不做。但是無論如何,它的***一行肯定應(yīng)該是SetActive(),讓自己成為活動狀態(tài)。
RunL負責具體的工作,如果是剛才Start了一個異步操作,此時應(yīng)該處理該操作結(jié)束后的事務(wù)(如上篇中加載了圖像以后就可以顯示到屏幕上了)。如果剛才沒有Start一個異步操作,那現(xiàn)在也得做點事情了。
有一種情況,我們把一個大任務(wù)分解成多個小任務(wù),放在RunL中來做,那就得再加一個狀態(tài)TInt iState來記錄此次回調(diào)應(yīng)該做哪一步小任務(wù)了(每完成一個小任務(wù)就改一個iState的值,并且還得再SetActive,讓這個活動對象繼續(xù)處于活動狀態(tài),直到所有任務(wù)完成)。
DoCancel提供了用戶可以中止活動任務(wù)的手段,而RunError則提供了錯誤處理的機會。
另外,在這個CActive的子類中,應(yīng)該有一個地方(一般是在ConstructL中)將自己放入調(diào)度器的隊列中,即調(diào)用CActiveScheduler::Add(this)。
帖一段代碼,就是上篇加載JPEG圖像的代碼應(yīng)該放在一個AO中來實現(xiàn),利用向?qū)梢粋€CActive的子類:
...{
public:
~CImageLoader();
// Two-phased constructor.
static CImageLoader* NewL(CDemoUIAppView *p);
static CImageLoader* NewLC(CDemoUIAppView *p);
public: // New functions
void StartL( );
private:
CImageLoader();
void ConstructL();
private: // From CActive
void RunL();
void DoCancel();
TInt RunError( TInt aError );
private:
RFs iRFs;
CDemoUIAppView *iParent;
CImageDecoder *iDec;
};
cpp中的實現(xiàn)更簡單了,在StartL中負責剛才的加載jpeg圖像(主要是它有一個異步調(diào)用),在RunL中負責重繪CDemoUIAppView的界面即可。
...{
Cancel(); // Cancel any request, just to be sure
if(iDec)
iDec->Cancel();
delete iDec;
iDec=NULL;
iDec = CImageDecoder::FileNewL(iRFs,KJPEGFile);
iParent->iBkImageMask=new (ELeave) CFbsBitmap();
iParent->iBkImageMask->Create( iDec-> FrameInfo().iOverallSizeInPixels,iDec-> FrameInfo().iFrameDisplayMode );
iDec->Convert( &iStatus, *(iParent->iBkImageMask) );
SetActive(); // Tell scheduler a request is active
}
void CImageLoader::RunL()
...{
if(iParent)
iParent->DrawNow();
【編輯推薦】