天道酬勤

 

Symbian编程总结-基础篇-活动对象正解(2)-使用活动对象(转)

一、活动对象工作流程

  首先我们用时序图来说明一下应用程序、活动对象、活动调度器及异步函数服务器之间创建及调用的流程:

Symbian编程总结-基础篇-活动对象正解(3)-活动对象的工作原理

  下面我们针对每一个步骤结合代码(点击此处下载代码)进行说明:

  1、创建并安装活动调度器:

CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
  CleanupStack::PushL(scheduler);
  CActiveScheduler::Install(scheduler);

  如果创建了一个基于GUI应用程序框架的应用程序,框架已经为我们创建并且安装了活动调度器,我们可以直接使用CActiveScheduler的一系列方法。

  2、创建活动对象

iMyAO = CMyActiveObject::NewL(*console);

  此处创建的CMyActiveObject类是继承自CActive类的活动对象。

  3、将活动对象添加到活动调度器中

void CMyActiveObject::ConstructL()
  {
  ....
  CActiveScheduler::Add( this); // Add to scheduler
  }

  可以看到,活动对象在通过“二阶段构造”创建时就已经将自己的指针添加到了活动调度器中。

  4、StartL

  StartL为应用程序请求活动对象调用异步函数的方法,此处用户可以根据自身需求对此方法重新命名:

 

void CMyActiveObject::StartL(TTimeIntervalMicroSeconds32 aDelay)
  {
  Cancel(); // 取消异步函数请求
  iStatus = KRequestPending;
  iTimer.After(iStatus, aDelay); // 在此处调用异步函数
  SetActive(); // 将成员变量iActive = ETrue
  }

  因为不能保证用户在等待异步函数调用完毕返回的时候不重新调用StartL方法,所以在StartL方法的入口点首先调用Cancel()方法取消异步请求,否则可能会发生臭名远扬的“信号迷失”错误。

  5、iStatus = KRequestPending

  在以上代码StartL方法中,异步函数调用之前,首先要将iStatus设置为KRequestPending以便活动调度器遍历时匹配。

  6、请求异步函数并发送iStatus

  在StartL方法中,iTimer.After(iStatus, aDelay);这行代码传递了成员变量的引用并调用了异步函数iTimer.After。

  7、SetActive

  调用基类CActive的SetActive方法,方法内部将iActive设置成ETrue,以便活动调度器遍历时匹配。

  8、启动活动调度器

CActiveScheduler::Start();

  10、查找对应的活动对象

  我们在上一节已经通过分析并还原了CActiveScheduler::Start()方法的伪代码,此代码块在另外一个线程遍历所有向调度器注册的活动对象,查看对象的iStatus不为KRequestPending且iActive为ETrue。因为异步函数服务器完成了请求的工作以后,会改变iStatus的实参,使其不等于KRequestPending,再加上活动对象在调用完异步函数返回后马上改变了iActive值为ETrue,所以活动调度器只要判断iStatus != KRequestPending && iActive == ETrue则可以知道那一个活动对象所请求的异步服务已经完成。

 

  9、WaitForAnyRequest()等待异步函数返回通知,11、RequestComplete()并将iStatus的值改变

  当异步服务已经完成了所请求的工作,它会使用User::RequestComplete()发送一个通知,活动调度器会通过User::WaitForAnyRequest()或RThread::WaitForAnyRequest()收到这个通知,随后遍历向其注册的条件匹配的活动对象(第8点下划线部分说明)。

  12、调用RunL方法

  如果找到了异步函数所对应的活动对象,则调用活动对象的RunL方法,RunL方法在TRAP宏里运行。如果RunL方法抛出异常,活动调度器会自动调用活动对象的RunError方法。因此大多数情况下不需要在RunL内编写异常捕获的代码。

  活动对象调用完RunL方法后,将活动对象的iActive值设置为EFalse,以便在下次遍历集合时跳过已经处理过的活动对象。

  如果没有找到异步函数所对应的活动对象,活动调度器将抛出一个“信号迷失”异常。

  13、CActiveScheduler::Stop()

  停止活动调度器,停止监控异步函数返回的信号。

  二、活动对象专属错误-“信号迷失”

  从上面的分析我们知道,活动调度器会拦截异步函数返回的消息,随后遍历活动对象集合找到相应的活动对象调用,如果没有找到则抛出“信号迷失”异常。有以下两种方法会导致“找不到活动对象”的发生:

  活动对象根本没有注册到活动调度器中:没有调用CActiveScheduler::Add方法注册活动对象

  不满足活动调度器查找活动对象的标准iStatus != KRequestPending && iActive == ETrue:在调用异步函数后,没有调用SetActive()方法将iActive的值设为ETrue;或者将iStatus同时传给两个异步函数,导致第二个异步函数返回时,当前活动对象的iActive为EFalse,调度器找不到相应的活动对象。

posted on 2009-05-23 22:37 程程 阅读(115) 评论(0)  编辑 收藏 引用 所属分类: symbian 学习


只有注册用户登录后才能发表评论。
网站导航:   博客园   博客园最新博文   博问   管理


导航

统计

常用链接

留言簿

随笔档案

文章分类

文章档案

搜索

最新评论