活动对象在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函数的