活動對象在symbian中應該來說是使用比較常用的一中機制,在這裏總結下使用活動對象的幾種方式。
活動對象的定義:一種模擬多線程實現多任務的一種機制,簡單的理解應該是這樣的。
具體使用:
1。配合RTime類來使用,基本上很多書上都是這麼寫(白皮書上就是這麼講的),我在這裏就不多說。
2。配合一些異步函數。比如寫文件的時候用到的Write函數,原型是:
IMPORT_C void Write(const TDesC8 &aDes, TRequestStatus &aStatus);
可以看到這裏的參數和其他的幾個函數有點差別,這裏有個TRequestStatus &aStatus參數,於是我們就聯想到,這個參數在活動對象中有用到。
用法如下:
a。激活活動對象
void CAsyncFile::FileWrite(const TDesC8& aDes)
{
TInt pos = 0;
iFile.Seek(ESeekEnd, pos);
iFile.Write(aDes, iStatus);
SetActive();
}
b.處理活動對象的RunL函數
void CAsyncFile::RunL()
{
switch(iStatus.int())
{
case KErrNone:
//do something
break;
}
}
c.往後的一些處理都和1中的一樣
還有比如連網的時候使用的IMPORT_C void RConnect::Start(TConnPref &aPref, TRequestStatus &aStatus);都是如同2中的使用方法
3。長時間的運行任務,用活動對象實現。我如要是爲了說下這種方法所以第1和2都講的比較簡單
這種方法應該也是常用的,但是可以網上資料沒有這麼實現的,貼下詳細代碼:
a。活動對象的.h
class CAoTest : public CActive
{
private:
void RunL();
TInt RunError(TInt aError);
void DoCancel();
public:
CAoTest();
~CAoTest();
void Start();
};
b.活動對象的.cpp
CAoTest::CAoTest() : CActive(EPriorityStandard)
{
CActiveScheduler::Add(this);
}
CAoTest::~CAoTest()
{
Cancel();
}
/*
在調用Start函數後會掉用這個函數,我們在這裏做了些處理,這樣直接讓活動對象調用完RunL函數後,
後再次調用RunL()函數,實現一個長期運行的活動對象
*/
void CAoTest::RunL()
{
TRequestStatus *myStatus = &iStatus;
User::RequestComplete(myStatus,KErrNone);
SetActive();
}
/*
處理取消活動對象,一般情況下可以這麼寫,都的時候需要空着,具體在使用的時候再體會吧
*/
void CAoTest::DoCancel()
{
TRequestStatus* pS = &iStatus;
User::RequestComplete(pS, KErrCancel);
}
/*
啓動函數,調用啓動活動對象。這裏需要注意的是需要設置iStatus這個值,直接設置爲KRequestPending
也可以,但是一般不推薦這樣直接賦值(初始化的時候可以這樣),容易出現E32Ueser-cbase 46(出現遊
離信號),可以像我下面那樣設置
*/
void CAoTest::Start()
{
// Cancel();
TRequestStatus* pS = &iStatus;
User::RequestComplete(pS, KErrNone);
if(!IsActive())
SetActive();
}
/*
處理Runl的異常退出,因此在Runl中就不用使用TRDP等異常處理的機制來處理異常了
*/
TInt CAoTest::RunError(TInt aError)
{
TInt nerr = aError;
return nerr;
}
CHelloWorldA0AppView* CHelloWorldA0AppView::NewL(const TRect& aRect)
{
CHelloWorldA0AppView* self = CHelloWorldA0AppView::NewLC(aRect);
CleanupStack::Pop(self);
return self;
}
c.使用活動對象
直接建立一個Hello world的GUI工程
然後在cantainer中 定義個成員
CAoTest *iaoTest;
然後在cantainer的ConstructL中實例化
void CHelloWorldA0AppView::ConstructL(const TRect& aRect)
{
// Create a window for this application view
CreateWindowL();
iaoTest = new CAoTest;
// Set the windows size
SetRect(aRect);
// Activate the window, which makes it ready to be drawn
ActivateL();
iaoTest->Start();
}
這個時候可以debug下單步運行,在RunL函數看見會不停的回調這個函數。這個時候一個長期運行的活動對象就成功實現
一般會遇到的問題問題:
1。一般在使用活動對象的時候遇到的比較常見的panic就是E32Ueser-cbase 46,對應的問題是說遊離的信號,
2。一般可能會出現遊離信號的情況是:
a.忘記激活活動對象,意思是忘記調用SetActive
b.忘記初始化iStatus爲KRequestding
c.出現兩次請求或者完成了兩次請求,這種情況一般是 因爲手動設置iStatus造成的
3.活動對象中不要直接調用DoCancel,而應該通過調用Cancel來間接的調用DoCancel
4.活動對象析構的時候一般都是會調用Cancel函數的