Symbian學(xué)習(xí)筆記(6)——關(guān)于多線程與活動(dòng)對(duì)象
既然如此,那我們就不說(shuō)“多線程”,說(shuō)說(shuō)“多任務(wù)”吧,活動(dòng)對(duì)象(Active Object)提供了非搶占式的多任務(wù)協(xié)同處理機(jī)制,它不是多線程的,而是運(yùn)行在一個(gè)單線程中。
AO機(jī)制包括兩個(gè)類(lèi)CActiveScheduler和CActive:
調(diào)度器CActiveScheduler:顧名思義它是協(xié)調(diào)多個(gè)活動(dòng)對(duì)象的調(diào)度者。既然是非搶占式的,那它的調(diào)度原則是什么呢?教材上說(shuō)法是:
A) 根據(jù)活動(dòng)對(duì)象的優(yōu)先級(jí)順序?qū)σ炎?cè)的所有活動(dòng)對(duì)象逐個(gè)檢查。
B) 判斷它是否是活動(dòng)的(IsActive),且它的iStatus是否不為KRequestPending。
C) 滿(mǎn)足則執(zhí)行它的RunL方法。
活動(dòng)對(duì)象CActive:這可以理解為一個(gè)“線程”,就象Java中的Runable。它受調(diào)度器的指揮,它的關(guān)鍵在于類(lèi)型為T(mén)RequestStatus的iStatus成員變量。
一般情況下在CActive中會(huì)有一個(gè)異步操作(方法形參表中包括一個(gè)TReuqestStatus類(lèi)型參數(shù)),如果沒(méi)有也無(wú)所謂(根據(jù)上面的調(diào)度原則,只要保證它不為KRequestPending即可)。
因?yàn)镚UI應(yīng)用自帶了CActiveScheduler,所以我們要做的事情就是實(shí)現(xiàn)一個(gè)派生于CActive的子類(lèi),重載方法RunL()、DoCancel()和RunError()。當(dāng)然還應(yīng)該有一個(gè)類(lèi)似于Start的方法來(lái)啟動(dòng)它。
Start負(fù)責(zé)啟動(dòng),一般是在這里去執(zhí)行一個(gè)異步操作(比如加載JPEG的圖像,如上篇所言;或者打開(kāi)一個(gè)定時(shí)器,如書(shū)上例子)。如果沒(méi)有異步操作的話(huà),也可以在這里啥事都不做。但是無(wú)論如何,它的***一行肯定應(yīng)該是SetActive(),讓自己成為活動(dòng)狀態(tài)。
RunL負(fù)責(zé)具體的工作,如果是剛才Start了一個(gè)異步操作,此時(shí)應(yīng)該處理該操作結(jié)束后的事務(wù)(如上篇中加載了圖像以后就可以顯示到屏幕上了)。如果剛才沒(méi)有Start一個(gè)異步操作,那現(xiàn)在也得做點(diǎn)事情了。
有一種情況,我們把一個(gè)大任務(wù)分解成多個(gè)小任務(wù),放在RunL中來(lái)做,那就得再加一個(gè)狀態(tài)TInt iState來(lái)記錄此次回調(diào)應(yīng)該做哪一步小任務(wù)了(每完成一個(gè)小任務(wù)就改一個(gè)iState的值,并且還得再SetActive,讓這個(gè)活動(dòng)對(duì)象繼續(xù)處于活動(dòng)狀態(tài),直到所有任務(wù)完成)。
DoCancel提供了用戶(hù)可以中止活動(dòng)任務(wù)的手段,而RunError則提供了錯(cuò)誤處理的機(jī)會(huì)。
另外,在這個(gè)CActive的子類(lèi)中,應(yīng)該有一個(gè)地方(一般是在ConstructL中)將自己放入調(diào)度器的隊(duì)列中,即調(diào)用CActiveScheduler::Add(this)。
帖一段代碼,就是上篇加載JPEG圖像的代碼應(yīng)該放在一個(gè)AO中來(lái)實(shí)現(xiàn),利用向?qū)梢粋€(gè)CActive的子類(lèi):
...{
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中的實(shí)現(xiàn)更簡(jiǎn)單了,在StartL中負(fù)責(zé)剛才的加載jpeg圖像(主要是它有一個(gè)異步調(diào)用),在RunL中負(fù)責(zé)重繪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();
【編輯推薦】