深入探索Symbian活动对象开发

Author:孙东风

Date:04/02/2008

        Active Object是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()
{
 ShowDialog(iCount++);

 //iTimer.After(iStatus, 1000000); // Set for 1 sec later
 SetActive();     // Tell scheduler a request is active
}

        既然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的测试例子,实现了一个动画:

/*
============================================================================
 Name        : ActiveTest3NewClass.h
 Author      : DongfengSun
 Version     : 04/02/2008
 Copyright   : Your copyright notice
 Description : CActiveTest3NewClass declaration
============================================================================
*/

#ifndef ACTIVETEST3NEWCLASS_H
#define ACTIVETEST3NEWCLASS_H

#include <e32base.h> // For CActive, link against: euser.lib
#include <e32std.h>  // For RTimer, link against: euser.lib

class CActiveTest3NewClass : public CActive
{
public:
 CActiveTest3NewClass();
 void ConstructL();
 ~CActiveTest3NewClass();

public: // New functions
 void StartL(TTimeIntervalMicroSeconds32 aDelay);
 void ShowDialog(TInt aCount);

private: // From CActive
 void RunL();
 void DoCancel();

private:
 enum TActiveTest3NewClassState
 {
     EUninitialized,
     EInitialized, 
     EError   
 };

private:
 TInt    iState; 
 RTimer iTimer;
 TInt iCount;

};

#endif

/*
============================================================================
 Name        : ActiveTest3NewClass.cpp
 Author      : DongfengSun
 Version     : 04/02/2008
 Copyright   : Your copyright notice
 Description : CActiveTest3NewClass implementation
============================================================================
*/

#include "ActiveTest3NewClass.h"
#include "aknnotewrappers.h"

CActiveTest3NewClass::CActiveTest3NewClass() : CActive(EPriorityStandard) 
{
 ConstructL();
}

void CActiveTest3NewClass::ConstructL()
{
 User::LeaveIfError(iTimer.CreateLocal()); 
 CActiveScheduler::Add(this);    
}

CActiveTest3NewClass::~CActiveTest3NewClass()
{
 Cancel();
}

void CActiveTest3NewClass::DoCancel()
{
 iTimer.Cancel();
}

void CActiveTest3NewClass::StartL(TTimeIntervalMicroSeconds32 aDelay)
{
 Cancel();  
 iState = EUninitialized;
 iTimer.After(iStatus, aDelay);
 TRAPD(ERROR,SetActive()); 
 TBuf<12> iBuf;
 iBuf.AppendNum(ERROR);
 CEikonEnv::Static()->InfoMsg(iBuf);
}


void CActiveTest3NewClass::ShowDialog(TInt aCount)
{
 TBuf<32> iBuf;
 iBuf.operator += _L("The index is :");
 iBuf.AppendNum(aCount);
 CAknInformationNote* iInfoNote = new (ELeave) CAknInformationNote;
 iInfoNote->ExecuteLD(iBuf);
}

void CActiveTest3NewClass::RunL()
{
 if (iState == EUninitialized) {
  iState = EInitialized;
 } else if (iState != EError) {
 }
 ShowDialog(iCount++);
 iTimer.After(iStatus, 1000000); 
 SetActive();     
}

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值