Symbian也是多任務(wù)操作系統(tǒng),當(dāng)然也要用進(jìn)程、線程完成多任務(wù)處理。進(jìn)程是程序的運(yùn)行實(shí)例,有自己獨(dú)立的數(shù)據(jù)空間。線程是進(jìn)程的執(zhí)行單元,一個(gè)進(jìn)程至少有一個(gè)主線程。多線程可以并發(fā)運(yùn)行采用搶占式完成多任務(wù)處理。但是Symbian下不提倡使用多線程,因?yàn)镾ymbian系統(tǒng)是通過客戶端/服務(wù)器結(jié)構(gòu)來提供對(duì)線程資源的訪問,這就意味著訪問線程需要與內(nèi)核的服務(wù)器程序不斷地進(jìn)行通信,效率低。
在單線程內(nèi),配合使用活動(dòng)對(duì)象+異步函數(shù),完全可以模擬多線程并行運(yùn)行。不同的是,這是一種非搶占式并行運(yùn)行,即當(dāng)前活動(dòng)對(duì)象結(jié)束之前,其它活動(dòng)對(duì)象不能運(yùn)行。 異步函數(shù)在執(zhí)行后立即返回,繼續(xù)執(zhí)行它下面的代碼。異步操作有后臺(tái)繼續(xù)執(zhí)行,結(jié)束后通過信號(hào)量表示異步操作結(jié)束。同步函數(shù)必須函數(shù)內(nèi)所有操作全部執(zhí)行結(jié)束后才能返回,執(zhí)行下面的代碼,否則就阻塞在那里。很顯然,實(shí)現(xiàn)多任務(wù)并行運(yùn)行必須使用異步函數(shù)。
活動(dòng)對(duì)象是CActive的派生類,設(shè)立它的作用就是為了提供一個(gè)專門用來調(diào)用異步函數(shù)的類。因?yàn)檫@個(gè)類中專門設(shè)有回調(diào)函數(shù),使異步函數(shù)結(jié)束后,能利用這個(gè)回調(diào)函數(shù)進(jìn)行尾處理。這個(gè)函數(shù)就是RunL()。在活動(dòng)對(duì)象外面使用異步函數(shù),只能截獲信號(hào)量,不能直接進(jìn)入某個(gè)回調(diào)函數(shù)。
異步函數(shù)結(jié)束后,是如何進(jìn)入到正確的回調(diào)函數(shù)中的呢?系統(tǒng)運(yùn)行著一個(gè)活動(dòng)調(diào)度器(CActiveSchedule),它能截獲異步函數(shù)結(jié)束后發(fā)出的信號(hào)量,并根據(jù)這個(gè)信號(hào)量,調(diào)用相應(yīng)的RunL()。問題是如果CActiveSchedule截獲了這個(gè)信號(hào),但卻找不到該調(diào)哪個(gè)活動(dòng)對(duì)象的RunL()怎么辦?這時(shí)CActiveSchedule會(huì)拋出異常,這種狀態(tài)叫信號(hào)游離,這種狀況經(jīng)常發(fā)生,所以使用活動(dòng)對(duì)象應(yīng)該避免這種情況發(fā)生。
哪些情況會(huì)產(chǎn)生游離信號(hào)?理解這個(gè)問題首先要了解CActiveSchedule如何判斷這個(gè)信號(hào)是不是游離信號(hào)。CActiveSchedule判斷游離信號(hào)的條件是
for(I=0;I<NUMBERS_OF_ACTIVE_OBJECT;I++)
{
IF(ACTIVE_OBJECTS[I].iActive==ETrue&&ACTIVE_OBJECTS[I].iStatus!=KRequestPending)
{
//由此可見,規(guī)則有二
//規(guī)則1 根本就沒有這個(gè)活動(dòng)對(duì)象
//規(guī)則2 活動(dòng)對(duì)象不是“活”的 ACTIVE_OBJECTS[I].RunL();
}
}
所以有如下情況可能會(huì)導(dǎo)致出現(xiàn)游離信號(hào)出現(xiàn)
1.沒有調(diào)用CActiveSchedule::Add(this);把活動(dòng)對(duì)象加到活動(dòng)調(diào)度器中。
2.沒有調(diào)用SetActive把活動(dòng)對(duì)象激活。破壞規(guī)則(2)
3.在活動(dòng)對(duì)象外調(diào)用異步函數(shù)后,沒有用User::WaitForRequest()截獲異步函數(shù)完成信號(hào)量。信號(hào)量進(jìn)入循環(huán)卻找不到活動(dòng)對(duì)象,破壞規(guī)則1。
4.同時(shí)一個(gè)活動(dòng)對(duì)象中同時(shí)調(diào)用兩個(gè)異步函數(shù)。如:InvokeAsyncFunc1();SetActice();InvokeAsyncFunc2();SetActive();第一個(gè)異步函數(shù)結(jié)束后,執(zhí)行完回調(diào)函數(shù)RunL()后,會(huì)把iActive置為EFalse,這時(shí)第二異步函數(shù)的結(jié)束信號(hào)進(jìn)入時(shí),卻發(fā)現(xiàn)活動(dòng)對(duì)象不是“活”的,破壞規(guī)則2。所以在一個(gè)活動(dòng)對(duì)象不能同時(shí)調(diào)用多個(gè)異步函數(shù)。