Symbian精彩活動對象徹底理解_第1頁
Symbian精彩活動對象徹底理解_第2頁
Symbian精彩活動對象徹底理解_第3頁
已閱讀5頁,還剩22頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、Symbian 活動對象徹底理解收藏Symbian編程總結(jié)-基礎(chǔ)篇-活動對象正解(1 )-理解活動對象Symbian OS中的活動對象的使用無疑是最基礎(chǔ)的、最頻繁的、最重要的。什么是活動對象呢?大家學(xué)習(xí)一個新的事物時,總是會將這個新的事物與自己認(rèn)知的事物相比較,從而達(dá)到快速學(xué)習(xí)的目的。我開始學(xué)習(xí)Symbian的時候,我查看很多 Symbian書籍、網(wǎng)上很多Symbian 教程都將活動對象與多線程聯(lián)系到一起,我也總是會把活動對象想象成一個線程。然而,經(jīng)過了更深入的接觸,我發(fā)現(xiàn)并不像我想象的那樣?,F(xiàn)在,我在此向你保證:活動對象和多線程沒有任何關(guān)系!不要拿平時做多線程的思想去理解活動對象!活動對象可

2、以按照以下步驟這么理解:Symbian OS 中提供了很多異步函數(shù),這些異步函數(shù)大多部分都是基于“服務(wù)器-客戶端”架構(gòu)的。這里與 wi n32 api中的函數(shù)有很大的不同。如:Win32中,CSocket:Receive (是recv而不是 WSARecv )為同步函數(shù),線程阻塞在 Receive處,直到套接字接收到了網(wǎng)絡(luò)流才返回。Symbian OS也有類似的函數(shù),RSocket:Receive ,但是此函數(shù)是一個異步函數(shù),線程不會阻塞在Receive處而會繼續(xù)執(zhí)行。如何區(qū)分Symbian中的函數(shù)哪些是同步的哪些是異步的?很簡單:看函數(shù)內(nèi)是否包含類型為TRequestStatus的形參,如果

3、有則函數(shù)為異步函數(shù)。如RSocket:Receive的函數(shù)原型為:IMPORT_C void Recv(TDes8 &aDesc, TUint flags, TRequestStatus&aStatus);參數(shù)aStatus為一個狀態(tài)位,初始值為ERequestPending (值為1),它意味著用戶請求的操作是否執(zhí)行完畢。如:我們調(diào)用異步函數(shù)RSocket:Receive 請求接收網(wǎng)絡(luò)流,Receive函數(shù)會直接返回。當(dāng)“接收”網(wǎng)絡(luò)流的過程完畢后,aStatus會變?yōu)镋Active,所以我們只要監(jiān)視aStatus是否不為ERequestPending就可以知道“接收”是否完成

4、了。我們可以使用以下偽代碼完成以上所述操作:TRequestStatusstatus(KRequestPending);RSocket:Receive(aDesc,flags, status);for(;)if (status != KRequestPe ndi ng) break; /此 處我們 已 經(jīng)通過RSocket:Receive 完成了類似CSocket:Receive 的同步的工作 Symbian OS 不建議我們使 用以上方法,它建議我們使用異步方法,而不要使用我們這種方法去強制同步,活動對象就是幫我們 做這件 事情?;?動對象 體系幫我們監(jiān)視 aStatus 的值,只要aSta

5、tus != ERequestPending ,他就會以事件的方式通知我們,告訴我們“Socket已經(jīng)接收完畢,你可以去取數(shù)據(jù)了! ”,活動對象就是干這事的??偨Y(jié)一下:系統(tǒng)中有一個“活動調(diào)度器”,我們建立一個“活動對象ao1 ”,將該對象與某個系統(tǒng)中的異步函數(shù)綁定,然后將該活動對象注冊到“活動調(diào)度器”中,“活動調(diào)度器”會等待異步函數(shù)返回的“完成”消息。收到完成消息后,調(diào)度器遍歷所注冊的活動對象,如果發(fā) 現(xiàn)status != KRequestPending則找到該status對應(yīng)的"活動對象 ao1 ”,調(diào)用其中的 RunL方法,以事件的方式告知我們異步函數(shù)已經(jīng)執(zhí)行完成。Symbian

6、編程總結(jié)-基礎(chǔ)篇-活動對象正解(2)-使用活動對象我們已經(jīng)大致了解了活動對象的基本概念,要使用活動對象機制, 需要用到活動對象、 活動調(diào)度器、異步函數(shù)。我們想使用異步函數(shù),要按照應(yīng)用程序-> 活動對象-> 活動調(diào)度器-> 異步函數(shù)的流程來使用。接下來我們開始進(jìn)入實戰(zhàn),使用活動對象。一、創(chuàng)建活動調(diào)度器我們知道,活動調(diào)度器是應(yīng)用程序和異步函數(shù)之間的橋梁,應(yīng)用程序使用活動對象通過活動調(diào)度器去截獲異步函數(shù)的返回“完成”消息,并以事件的方式通知應(yīng)用程序。使用Carbide C+1.3,通過模板向?qū)傻目刂婆_程序自動為我們生成了創(chuàng)建活動調(diào)度器的代碼:CActiveScheduler*s

7、cheduler = new (ELeave) CActiveScheduler();CActiveScheduler:l nstall(scheduler);CActiveScheduler:l nstall()方法調(diào)用以后,內(nèi)部代碼就會將scheduler指針賦值給CActiveScheduler類內(nèi)部的靜態(tài)指針,后面的代碼就可以方便的使用CActiveScheduler類的靜態(tài)方法,如:IMPORT_C static void Add(CActive* aActive);IMPORT_C static void Start();IMPORT_C static void Stop();Ad

8、d() 方法:將活動對象加入活動調(diào)度器中注冊,以備使用Start()方法:啟動活動調(diào)度器,活動調(diào)度器將開始循環(huán)等待異步函數(shù)返回的通知消息Stop()方法:停止活動調(diào)度器二、創(chuàng)建活動對象1、我們創(chuàng)建的活動對象必須派生自CActive類,CActive類已經(jīng)為我們準(zhǔn)備好了iStatus成員變量:public:TRequestStatus iStatus;private:TBool iActive; 另外一個成員變量 iActive起著標(biāo)識作用,證明該活動對象已經(jīng)請求了異步函數(shù),如:RTimer:After(iStatus, 1000000);SetActive(); SetActive()方法為基

9、類 CActive 的方法,其實就是將iActive = ETrue;,用來標(biāo)識活動對象已經(jīng)調(diào)用了異步函數(shù)。所以,我們只要調(diào)用 了異步函數(shù),在調(diào)用異步函數(shù)的代碼后面應(yīng)該緊挨著調(diào)用SetActive()方法的代碼。2、有兩個虛方法必須繼承:virtual void DoCancel() =0;virtual void RunL() =0;RunL 方法:活動調(diào)度器接收到異步函數(shù)返回的“完成”消息后,遍歷在其注冊的所有活動對象,如果活動對象的iActive=ETrue 且iStatus != KRequestPending則調(diào)用活動對象的 RunL方法,并將iActive 設(shè)置成EFalse,以防

10、下次輪詢時仍然調(diào)用此活動對象。在這里“ RunL ”這個名字會讓很多人產(chǎn)生歧義,我剛開始接觸的時候總以為和J2me中的Runnable 接口的run方法差不多。其實在這里把“RunL "改為"NotifyRequestCompleteL”更貼切些。再次聲明一下,調(diào)用異步函數(shù)時,參數(shù)TRequestStatus& status都是以引用的方式傳遞的,如:IMPORT_C void After(TRequestStatus& aStatus,TTimel ntervalMicroSeco nds32anln terval);所以異步函數(shù)內(nèi)部可以改變status的

11、實參,也就是改變活動對象的類成員iStatus。DoCancel()方法:基類 CActive中有取消異步函數(shù)的方法Cancel(),調(diào)用Cancel()后,活動對象會通過DoCancel()方法通知應(yīng)用程序做取消方法的后期工作,如刪除對象及回收指針等。注意:在應(yīng)用程序中如果想終止活動對象,要使用Cancel()方法調(diào)用而不是 DoCancel()方法。3、活動對象的帶優(yōu)先級的構(gòu)造函數(shù):基類CActive的構(gòu)造函數(shù)原型如下:protected:IMPORT_C CActive(T Int aPriority);此處將傳入一個優(yōu)先級枚舉值,枚舉值內(nèi)容如下:/*Defi nes sta ndard

12、 priorities for active objects.*/e num TPriority/* Alow priority, useful for active objectsrepresentingbackgroundprocessing.*/ EPriorityldle=-100,/* A priority higher than EPriorityIdle butlower tha n EPrioritySta ndard.*/ EPriorityLow=-20,/* Mostactive objects will have this priority. */ EPriorityS

13、tandard=0,/* Apriority higher than EPriorityStandard;useful for active objectshandlinguserin put.*/ EPriorityUserl nput=10,/* A priority higher thanEPriorityUserl nput.*/ EPriorityHigh=20,;當(dāng)調(diào)用 CActiveScheduler:Add方法注冊活動對象時,活動調(diào)度器會按照活動對象的優(yōu)先級進(jìn)行排序,插入或添加到活動對象集合中。在此會起到如下作用:當(dāng)多個異步函數(shù)消息同時返回時(多個iStatus同時不為KReq

14、uestPending),活動對象調(diào)度器輪訓(xùn)集合的時候總是會先找到優(yōu)先級高的活動對象并調(diào)用其RunL方法。但是在通常情況下,我們會在構(gòu)造函數(shù)傳入EPrioritySta ndard。三、活動調(diào)度器 Start方法的偽代碼通過以上兩點分析,我們完全可以模擬出CActiveScheduler:Start 方法:void CActiveScheduler:Start() for (;)/ 掛起線程直到異步函數(shù)消息返回/注:活動調(diào)度器和應(yīng)用程序不在一個線程,所以應(yīng)用程序不會阻塞User:WaitForAnyRequest();/如果異步函數(shù)和主程序在不同的線程則RThread:WaitForA nyR

15、equest();/當(dāng)消息返回的時候線程會蘇醒/以優(yōu)先級降序的方式檢測調(diào)度器集合中每個活動對象for (;)/調(diào)用第一個已完成且iActive = ETrue的活動對象事件處理函數(shù)if (activeObject->lsActive()&& activeObject->iStatus !=KRequestPe ndi ng)/找到一個已準(zhǔn)備好處理事件的活動對象/重置iActive狀態(tài)以表明其不再是活動狀態(tài)了activeObject->iActiveEFalse;/在TRAP中調(diào)用活動對象的事件處理函數(shù)TRAPD(err,activeObject->Ru

16、nL()if (err !=KErrN one)/如果異常則調(diào)用活動對象的Run Error方法err=activeObject->R un Error();if(err!=KErrNo ne)Error(err); break;四、使用活動對象的例子點擊此處下載源代碼此例子將啟動一個控制臺程序,并使用異步服務(wù)類 RTimer定時器,每隔一秒在屏幕上顯示累加的數(shù)字,效果如下:五、小結(jié)在這一節(jié)中,我們基本了解了活動調(diào)度器、活動對象的工作機制及工作流程,在下一節(jié)里,我們將深入活動對象的內(nèi)部,了解其工作原理,進(jìn)一步加深對活動對象的理解。Symbian編程總結(jié)-基礎(chǔ)篇-活動對象正解(3)-活動對

17、象的工作原理我們已經(jīng)知道如何創(chuàng)建和使用活動對象,大家對活動對象的創(chuàng)建、使用都有了一定的了解。在這一節(jié)里我將深入活動對象機制,分為“活動對象的工作流程”、“信號迷失錯誤”兩個部分,為大家剖析活動對象的工作原理。一、活動對象工作流程首先我們用時序圖來說明一下應(yīng)用程序、活動對象、活動調(diào)度器及異步函數(shù)服務(wù)器之間創(chuàng)建及調(diào)用的流程:下面我們針對每一個步驟結(jié)合代碼(點擊此處下載代碼)進(jìn)行說明:1、創(chuàng)建并安裝活動調(diào)度器:CActiveScheduler*scheduler = new (ELeave) CActiveScheduler();Clea nupStack:PushL(scheduler);CAct

18、iveScheduler:l nstall(scheduler);如果創(chuàng)建了一個基于GUI應(yīng)用程序框架的應(yīng)用程序,框架已經(jīng)為我們創(chuàng)建并且安裝了活動調(diào)度器,我們可以直接使用CActiveScheduler的一系列方法。2、創(chuàng)建活動對象iMyAO = CMyActiveObject:NewL(*console);此處創(chuàng)建的 CMyActiveObject類是繼承自CActive類的活動對象。3、將活動對象添加到活動調(diào)度器中void CMyActiveObject:ConstructL(). CActiveScheduler:Add( this); /Add to scheduler可以看到,活動對

19、象在通過"二階段構(gòu)造”創(chuàng)建時就已經(jīng)將自己的指針添加到了活動調(diào)度器中。4、StartLStartL為應(yīng)用程序請求活動對象調(diào)用異步函數(shù)的方法,此處用戶可以根據(jù)自身需求對此方法重新命名:voidCMyActiveObject:StartL(TTimel ntervalMicroSeco nds32aDelay)Cancel();/ 取消異步函數(shù)請求iStatus = KRequestPending;iTimer.After(iStatus, aDelay); / 在此處調(diào)用異步函數(shù)SetActive(); / 將成員變量iActive = ETrue因為不能保證用戶在等待異步函數(shù)調(diào)用完畢返

20、回的時候不重新調(diào)用StartL方法,所以在 StartL方法的入口點首先調(diào)用Cancel()方法取消異步請求,否則可能會發(fā)生臭名遠(yuǎn)揚的“信號迷失”錯誤。5、iStatus = KRequestPending在以上代碼StartL方法中,異步函數(shù)調(diào)用之前,首先要將iStatus設(shè)置為KRequestPending以便活動調(diào)度器遍歷時匹配。6、 請求異步函數(shù)并發(fā)送iStatus在StartL方法中,iTimer.After(iStatus, aDelay);這行代碼傳遞了成員變量的引用并調(diào)用了異步函數(shù) iTimer.After。7、SetActive調(diào)用基類CActive的SetActive方法,

21、方法內(nèi)部將iActive設(shè)置成ETrue,以便活動調(diào)度器遍歷時匹配。8、啟動活動調(diào)度器CActiveScheduler:Start();10、查找對應(yīng)的活動對象我們在上一節(jié)已經(jīng)通過分析并還原了CActiveScheduler:Start() 方法的偽代碼,此代碼塊在另外一個線程遍歷所有向調(diào)度器注冊的活動對象,查看對象的iStatus 不為KRequestPending 且iActive為ETrue。因為異步函數(shù)服務(wù)器完成了請求的工作以后,會改變iStatus的實參,使其不等于KRequestPending,再加上活動對象在調(diào)用完異步函數(shù)返回后馬上改變了 iActive 值 為ETrue ,所以

22、活動調(diào)度器只要判斷iStatus !=KRequestPe nding && iActive = ETrue則可以知道哪一個活動對象所請求的異步服務(wù)已經(jīng)完成。9、WaitForAnyRequest()等待異步函數(shù)返回通知,11、RequestComplete() 并將 iStatus的值改變當(dāng)異步服務(wù)已經(jīng)完成了所請求的工作,它會使用User:RequestComplete()發(fā)送一個通知,活動調(diào)度器會通過User:WaitForAnyRequest()或 RThread:WaitForAnyRequest()收到這個通知,隨后遍歷向其注冊的條件匹配的活動對象(第8點下劃線部分說

23、明)。12、調(diào)用RunL方法如果找到了異步函數(shù)所對應(yīng)的活動對象,則調(diào)用活動對象的 RunL方法,RunL方法在TRAP宏里運行。如果 RunL方法拋出異常,活動調(diào)度器會自動調(diào)用活動對象的RunError方法。因此大多數(shù)情況下不需要在RunL內(nèi)編寫異常捕獲的代碼?;顒訉ο笳{(diào)用完 RunL方法后,將活動對象的iActive值設(shè)置為EFalse,以便在下次遍歷集 合時跳過已經(jīng)處理過的活動對象。如果沒有找到異步函數(shù)所對應(yīng)的活動對象,活動調(diào)度器將拋出一個“信號迷失”異常。13、CActiveScheduler:Stop()停止活動調(diào)度器,停止監(jiān)控異步函數(shù)返回的信號。二、活動對象專屬錯誤- “信號迷失”從

24、上面的分析我們知道,活動調(diào)度器會攔截異步函數(shù)返回的消息,隨后遍歷活動對象集合找到相應(yīng)的活動對象調(diào)用,如果沒有找到則拋出“信號迷失”異常。有以下兩種方法會導(dǎo)致“找不到活動對象”的發(fā)生:活動對象根本沒有注冊到活動調(diào)度器中:沒有調(diào)用對象CActiveScheduler:Add方法注冊活動不滿足活動調(diào)度器查找活動對象的標(biāo)準(zhǔn)iStatus!= KRequestPe nding&& iActive =ETrue :在調(diào)用異步函數(shù)后,沒有調(diào)用SetActive()方法將iActive的值設(shè)為ETrue ;或者將iStatus同時傳給兩個異步函數(shù),導(dǎo)致第二個異步函數(shù)返回時,當(dāng)前活動對象的iAc

25、tive為EFalse,調(diào)度器找不到相應(yīng)的活動對象。三、小結(jié)在這一節(jié)里,我們學(xué)習(xí)了活動對象的內(nèi)部工作原理,讓我們對活動對象處理機制有了更深入的了解。在下一節(jié)里,我們將學(xué)習(xí)如何同步調(diào)用現(xiàn)有的異步函數(shù)。Symbian編程總結(jié)-基礎(chǔ)篇-活動對象正解(4)-異步函數(shù)的同步調(diào)用我們深入了解了活動對象、活動調(diào)度器及異步函數(shù)服務(wù)器的工作原理及運行機制,想必大家對活動對象的機制及體系結(jié)構(gòu)的運用已經(jīng)了如指掌。但是大家有沒有覺得異步函數(shù)使用起來比較麻煩呢?難道非要使用活動對象,非得以”異步"的方式調(diào)用異步函數(shù)嗎?這一節(jié)將為大家解決這個問題:異步函數(shù)的同步使用。一、使用 CActiveSchedulerW

26、ait 類在以前的文章"Symbian編程總結(jié)-界面篇-打開jpeg/gif/png 圖像"里我們已經(jīng)看 到了 CActiveSchedulerWait類的使用方法,在此我再詳細(xì)介紹一下。很多初學(xué)者在開始時會將 CActiveScheduler 和CActiveSchedulerWait 類弄混, CActiveScheduler 是活動對象的調(diào)度器,而 CActiveSchedulerWait 可以簡單的理解為一 個當(dāng)前線程的阻塞器:調(diào)用 CActiveSchedulerWait:Start()方法時,線程阻塞;調(diào)用CActiveSchedulerWait:AsyncSt

27、op()方法時,請求停止對線程的阻塞因此,我們在不修改原來活動對象代碼的情況下,只要簡單的在異步函數(shù)調(diào)用方法后加上"CActiveSchedulerWait:Start()" ,在活動對象的 RunL 方法的開頭加入 "CActiveSchedulerWait:A nsycStop()"就可以了。針對上一節(jié)教程介紹的控制臺應(yīng)用程序,我們對以下幾個方法(下劃線為修改部分)進(jìn)行修改:點擊此處下載源代碼CActiveSchedulerWait* iWait;void CMyActiveObject:Co nstructL()User:LeavelfError(

28、iTimer.CreateLocal() ); /In itialize timerCActiveScheduler:Add( this); / Add to scheduleriWait = new (ELeave)CActiveSchedulerWait;CMyActiveObject:CMyActiveObject()Can cel(); / Can cel any request, if outsta ndingiTimer.Close(); / Destroy the RTimer object/ Delete in sta nce variables if anyif (iWait

29、->lsStarted()iWait->As yn cStop();delete iWait;iWait = NULL;void CMyActiveObject:StartL(TTimel ntervalMicroSeco nds32 aDelay)Can cel(); / Can cel any request, just to be sureiTimer.After(iStatus, aDelay); / Set for laterSetActive(); / Tell scheduler a request is activeiWait->Start(); / 第 1

30、點void CMyActiveObject:Ru nL()iWait->AsyncStop(); /第 2 點TBuf<50> outputStr;outputStr.Appe ndNum(iCou nt); iCo nsole.Write(outputStr); iCo nsole.Write(_L("n"); iCoun t+;使用CActiveSchedulerWait的幾點注意事項:CActiveSchedulerWait必須結(jié)合活動對象使用,而且使用方法只有以上代碼介紹的那一種;Start方法和AsyncStop 方法必須成對出現(xiàn);程序退出時 要

31、檢查 CActiveSchedulerWait 是否在IsStarted()狀態(tài),如果 是則調(diào)用Asy ncStop方法。否則程序不能正常退出;CActiveScheduler類內(nèi)部有自己的靜態(tài)指針,提供的靜態(tài)方法都調(diào)用了內(nèi)部的靜態(tài)指針。而CActiveSchedulerWait類沒有內(nèi)部靜態(tài)指針,方法也不是靜態(tài)的,我們必須自己管理CActiveSchedulerWait類的全局指針,在這點上程序要經(jīng)過良好的設(shè)計。二、使用 User:WaitForRequest 方法如果不想使用活動對象,也不想使用難于管理的CactiveSchedulerWait,你可以使用User:WaitForReque

32、st 方法。以下是 User:WaitForRequest方法的原型:IMPORT_C static void WaitForRequest(TRequestStatus & aStatus);此方法將等待異步函數(shù)服務(wù)器返回的信號量,然后匹配aStatus參數(shù)。如果接收到的信號與參數(shù)aStatus 一一匹配,則跳過阻塞進(jìn)入下一行代碼,否則繼續(xù)阻塞線程直到aStatus對應(yīng)的信號通知返回。User:WaitForRequest還有一個重載的方法,它可以監(jiān)視兩個信號的通知:IMPORT_C static void WaitForRequest(TRequestStatus & aS

33、tatus1,TRequestStatus &aStatus2);有了 User:WaitForRequest ,異步函數(shù)使用起來就變得非常方便,我們不需要創(chuàng)建活動對象,也不需要創(chuàng)建成員變量 TRequestStatus ,只需要聲明局部的TRequestStatus 、局部的異步函數(shù)類,在異步函數(shù)調(diào)用之后,加入處直到User:WaitForRequest(status),就能夠使線程阻塞在User:WaitForRequeststatus對應(yīng)的異步函數(shù)處理完成。LOCAL_C void DoTestL()RTimer timer;Clea nupClosePushL(timer);User:LeavelfError(timer.CreateLocal();TRequestStatus status(KRequestPe ndin g);/調(diào)用異步方法并將status傳入timer.After(status, 1000000);方法將異步方法的調(diào)II等待status對應(yīng)的信號量,此處用了User:WaitForRequest用模擬成同步User:WaitForRequest(status);Clea nupStack:Pop(&

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論