Author:孙东风
Date:04/02/2008
ActiveObject是Symbian中的一个重要概念,它是Symbian OS为了节省系统资源利用单线程来实现多任务异步处理的机制。
S60本身的Framwork也大量采用AO进行多任务的实现,例如我们可以在S60 EIKON Control based application中直接调用以下代码添加自身的AO到系统CActiveScheduler中。
void CActiveTest3NewClass::ConstructL()
{
User::LeaveIfError(iTimer.CreateLocal());// Initialize timer
CActiveScheduler::Add(this);// Add to scheduler
}
如果你有CustKit、DevKit或者BAK,那么跟踪Symbian程序的入口
GLDEF_C TInt E32Main()
{
return EikStart::RunApplication( NewApplication );
}
你会发现EikStart::RunApplication其实调用的就是CActiveScheduler::Start(),这个调用启动了一个CActiveScheduler并进入了CActiveScheduler的循环。而程序一旦进入了CActiveScheduler的循环后就不会跳出来,直到程序结束。
这一点很像Windows的消息循环机制:
while(getMessage(...))
{
TranslateMessage(...);
DispatchMessage(...);
}
CActiveScheduler维护着一个等待循环,这个等待循环用于接受所有活动对象发出的请求,然后交给相应的服务器程序进行处理。当请求得到响应后,服务器会产生一个事件,这个事件由RunL()函数处理,事件处理完后RunL()函数可以决定是继续发送下一个请求还是终止发出请求。
例如下面的程序就是RunL()处理后继续发送请求,从而让程序不断的循环:
void CActiveTest3NewClass::RunL() { ShowDialog(iCount++); SetActive();// Tell scheduler a request is active } |
当然上面这个循环太过于快速,有时候会出现"跳表"。那么可以采用一个RTimer进行时钟控制:
void CActiveTest3NewClass::RunL() //iTimer.After(iStatus, 1000000); // Set for 1 sec later |
既然CActiveScheduler负责AO的调度,那么明白CActiveScheduler的调度原则就显得很重要,CActiveScheduler的调度原则分为下面两条:
①根据AO的优先级顺序对已经add进来的AO逐个检查。
CActiveScheduler有一张AO表,按优先级从大到小的顺序记录它所拥有的AO。然后根据每个AO的优先级决定谁先得到服务器的响应。
②判断当前遍历到的AO的IsActive()值和iStatus状态。
在IsActive()为ETrue并且iStatus != KRquestPending时,才会把AO的请求提交给服务器程序。在接收到服务器的响应后,再执行AO的RunL()方法。
其中TRequestStatus iStatus是抽象基类CActive的一个状态变量,它是TRequestStatus类的对象,封装了服务器返回时提供的状态或错误码。当发出请求时,活动对象将iStatus的引用传递到服务器,服务器将iStatus的值设为KRequestPedding而阻塞其它请求。当请求完成时,服务器将iStatus的值设为KErrNone。
下面是我写的一个AO的测试例子,实现了一个动画:
/* #ifndef ACTIVETEST3NEWCLASS_H #include <e32base.h>// For CActive, link against: euser.lib class CActiveTest3NewClass : public CActive public: // New functions private: // From CActive private: private: }; #endif |
/* #include "ActiveTest3NewClass.h" CActiveTest3NewClass::CActiveTest3NewClass() : CActive(EPriorityStandard) void CActiveTest3NewClass::ConstructL() CActiveTest3NewClass::~CActiveTest3NewClass() void CActiveTest3NewClass::DoCancel() void CActiveTest3NewClass::StartL(TTimeIntervalMicroSeconds32 aDelay)
void CActiveTest3NewClass::RunL() |