`
totoxian
  • 浏览: 1027827 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

深入探索Symbian活动对象开发

阅读更多

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()
{
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;
RTimeriTimer;
TIntiCount;

};

#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();
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics