活动对象(Active_第1页
活动对象(Active_第2页
活动对象(Active_第3页
活动对象(Active_第4页
活动对象(Active_第5页
已阅读5页,还剩80页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Copyright 2001-2007 Symbian Software Ltd.Symbian OS基础 活动对象(Active Object)活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.2活动对象活动对象被用于事件驱动的多任务处理它们是 Symbian OS的一个基本部分本讲要讲解为什么活动对象非常重要 解释它们是如何怎样设计以进行响应式、高效率的处理事件Symbian OS基础课程目标Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.3活动对象Symbian OS

2、中的事件驱动多任务处理理解同步请求和异步请求的区别之处,并且能够对它们的典型进行区分认识活动对象的典型应用处理异步任务并且不阻塞线程时被请求理解用多线程和多活动对象实现多任务的区别,以及为什么后者在Symbian OS 编码中要优先使用活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.4Symbian OS 中的事件驱动多任务处理同步和异步请求当程序的函数代码中要调用一个服务请求时,这个服务不是同步执行就是异步执行同步同步函数 执行一个服务直到完成,然后返回其调用者,通常返回的是一个成功或者失败指示异步异步函数 提交一个请求作为函

3、数调用的一部分,并且马上返回到其调用者继续执行在一段时间之后请求再完成活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.5Symbian OS 中的多任务处理调用一个异步请求以后调用者可以自由处理其他问题或者简单的等待,后者就是常说的“阻塞”一旦服务完成,调用者可以接收到一个信号,显示请求是否成功这个信号就是一个事件这段代码被称为事件驱动定时器等待是一个典型的异步调用的例子另一个例子是Read()方法,它在Symbian OS的RSocket类中,这个方法是从远程主机收取数据活动对象Symbian OS基础Copyright 20

4、01-2007 Symbian Software Ltd.6Symbian OS 中的线程 线程被内核以抢占的方式调度内核执行已经就绪的最高优先级的线程每个线程都可能由于等待一个事件的发生而暂停执行,而在适当的条件下恢复执行内核控制线程的调度允许线程通过时间片分割的方式共享系统资源,如果有更高级的线程处于就绪态,则抢先执行这个高优先级的线程这种总是运行已就绪的最高优先级线程的方式是占先式多任务处理的基础活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.7Symbian OS中的线程当当前线程挂起时会发生上下文切换上下文切换导致了运

5、行时内核调度器的负载如果原来的和替换的线程在不同的进程执行,会因为要交换进程内存以及写入缓存而带来更大开销比线程上下文切换要慢100倍活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.8事件驱动多任务处理异步事件可发生在如下情况: 从外部资源例如用户输入或者硬件外设接收到数据。 通过软件例如由定时器或者完成异步请求时引起。活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.9事件驱动多任务处理事件由事件处理器管理事件处理器等待事件,然后处理它一个高层的事件处理器的应用是

6、网页浏览器应用等待用户输入和响应,提交请求以接收Web页,并把接收到的页面显示出来网页浏览器使用系统服务器,用以接收来自他客户端的请求。系统服务器接收到请求,并且继续等待另一个请求。在服务请求中,系统服务器依次将请求地交给其他的服务器,它们将稍后产生完成事件。这里描述的每个软件组建都是事件驱动的。它需要对用户输入或者来自系统的请求作出响应这样的话很快就会变得很复杂!活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.10Symbian OS 中事件处理考虑在响应一个事件的时候,事件处理器可能要请求另一个服务,而这将引发另一个事件(依

7、次类推)操作系统必须有一个高效的事件处理模型,从而在事件发生后通过最合适的顺序尽快处理他们对用户驱动的事件进行快速处理及给出响应以提供良好的用户体验是尤为重要的活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.11Symbian OS 中事件处理考虑要避免在事件之间持续的检测这样不断的检测会导致大量的功耗,这在电池供能的设备上必须避免操作系统在低能耗状态进行等待在等待下一个事件的时候,软件应允许操作系统转入空闲模式 事件处理应使内存资源使用最小化处理器资源也要有效的使用活动对象满足这些要求,并提供了一种轻量级的事件驱动多任务处理机

8、制活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.12活动对象和活动调度器活动对象和活动调度器(Active Scheduler)一起被称为“活动对象框架”用于简化异步程序设计,使编写代码更容易:提交异步请求 管理请求的完成事件对结果的处理 通常,一个Symbian OS应用程序或服务包含单个主事件处理线程和与其相关的活动调度器在线程中运行一组活动对象活动对象有的事件处理方法以供活动调度器调用每个活动对象封装了一个任务 它向其服务器提供者请求异步服务,并由活动调度器调用它处理请求完成事件活动对象Symbian OS基础Copyr

9、ight 2001-2007 Symbian Software Ltd.13活动对象和活动调度器活动对象框架被用于调度同一个线程中多个异步任务的处理所有活动对象都在同一个线程中运行,因此在活动对象中切换比线程间上下文切换的代价要低这就使得活动对象通常是Symbian OS 中最合适的事件驱动多任务处理机制活动对象在运行中是彼此独立的就像在进程中线程的运行时彼此独立的一样然而,由于在在同一线程中,活动对象更容易共享内存活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.14活动对象和活动调度器活动对象框架 是协作式或者非抢先的多任务处

10、理在线程中其他活动对象能够开始执行操作之前,每个活动对象的方法都会运行直到完成当活动对象在处理事件时它不能被线程中其他运行的活动对象所抢占注意线程本身的调度是抢先式的(见前面的幻灯片)活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.15活动对象和活动调度器一个Win32 应用(例如在Windows下运行的程序) 使用了一个简单的消息循环和消息分发的模式在 Symbian OS 中,活动调度器代替了Windows中的消息循环,活动对象的事件处理函数相当于消息处理函数由活动调度器执行的事件完成处理与事件引发的特定动作是解耦的它们由单

11、个活动对象执行例如:email 发送完成事件其处理动作就移开了”发送”对话框活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.16实时性考虑说明有些事件要求在有保证的时间内响应这被称为“实时”事件处理 例如一个实时任务可能被要求保持为一个声音驱动的缓冲区提供声音数据,相应延迟就会导致声音解码的延迟,其结果就是声音的中断另一个典型的实时要求可能更严格,例如底层的电话通信不同任务对实时响应有不同的需求这些可以用任务优先级表示 高优先级任务总必须能抢占低优先级任务,从而保证符合他们的实时性要求 任务要求的响应越短,它应赋予的优先级越高活

12、动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.17活动对象不适合实时任务 当一个活动对象在处理事件时,它无法被同一线程的另一个活动对象的事件处理程序所抢占因此,他们不适合实时任务在 Symbian OS中, 实时任务应当用高优先级线程和进程来实现,并根据相对的实时性要求选择适当的优先级Symbian OS基础课程目标Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.18活动对象CActive类类了解活动对象优先级别的重要性知道活动对象事件处理方法 (RunL() 是非抢占的

13、知道活动对象的继承特性,以及需要实现和覆盖的函数了解如何构建、使用和销毁活动对象活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.19 活动对象引言每个活动对象请求一个异步服务,并且在请求过后一段时间处理完成事件它也提供一种撤销未完成请求的方法,还有异常情况下的错误处理一个活动对象类必须派生自CActive 类,该类定义在e32base.h中活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.20活动对象类的构造CActive 类是一个抽象类,拥有两个纯虚函数RunL(

14、) 和 DoCancel() 所有具体的活动对象类必须从CActive类中继承,定义和实现这些方法它还拥有一个TRequestStatus 成员变量用以接收异步请求的完成结果在构造时从CActive派生的类必须调用基类中的保护型构造函数同时传递一个参数来设置活动对象的优先级 和线程类似,所有的活动对象都有一个优先级值来决定它们被如何调度活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.21为什么有活动对象优先级?当活动对象关联的异步服务完成时会产生一个事件,活动调度器能侦测到这个事件.1.活动调度器决定每个事件关联的是哪个活动对象

15、2.然后调用恰当的活动对象去处理事件当活动对象在处理事件时直到事件处理函数返回到活动调度器,它是无法被抢占的因此很可能很多事件在控制返回到活动调度器之前已经完成活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.22为什么有活动对象优先级?要解决哪个活动对象是下一个要运行的活动调度器通过活动对象的优先级进行排序,而不是根据完成的顺序否则,一个具有低优先级的事件,如果他在一个更重要的事件之前完成,那么它就会将高优先级事件的处理推迟一段时间,而这段时间的长度是不确定的优先级只是用来决定事件处理者运行的顺序的如果一个高优先级活动对象收到一

16、个事件处理请求,而此时一个低优先级的活动对象正处理事件,这个低优先级的事件处理器是不能被抢占的活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.23优先级定义了一系列的优先级在CActive 类中的TPriority 枚举类通常使用优先级 CActive:EPriorityStandard (=0),除非有很好的理由不去这么做活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.24活动对象类的构造作为构造的一额外部分,活动对象代码应当调用活动调度器的静态函数CActiv

17、eScheduler:Add()这可以将活动对象加入到那个线程中的事件处理活动对象列表中列表由活动调度器来维护列表用活动对象的优先级排序,最高优先级的活动对象在前面活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.25活动对象类的构造活动对象典型的拥有的一个对象的句柄向它发出异步完成的请求,例如RTimer 类型的定时器对象这个对象通常被认为是异步服务提供者,它可能需要作为活动对象构造的一部分被初始化如果初始化失败,它必须在第二阶段构造中执行活动对象Symbian OS基础Copyright 2001-2007 Symbian S

18、oftware Ltd.26提交异步服务请求活动对象类 会向调用者提供公有的请求发起方法以初始化请求这些方法通过建立好的模式向活动对象对应的异步服务者提交请求过段时间请求完成,产生一个事件如下所示.活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.27提交异步服务请求1. 检查以前的未完成请求请求方法应该检查在试图提交另一个请求之前没有请求已被提交了. 每一个活动对象只能有一个已未完成的请求. 依赖于实现,代码可能有如下几种情况:如果请求已经发出,就发生致命系统 (这种情况只会因为程序设计错误而发生)如果尝试提交多个请求是合法饿,

19、拒绝提交另一个请求,取消先前的请求并提交一个新的请求活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.28提交异步服务请求2. 请求的结果活动对象应该向服务提供者发送请求,传入其 TRequestStatus& 类型的iStatus成员变量作为参数服务提供者在开始异步请求之前要把这个值赋给 KRequestPending活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.29提交异步服务请求3. 调用 SetActive() 方法标识对象为“等待”状态如果请求被

20、成功的提交了,请求方法将调用CActive 基类中的SetActive()方法从而向活动调度器指明请求是已经被提交并且是未完成的只有在请求已经提交了以后,才能调用这个函数活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.30事件处理每个活动对象类 必须实现 CActive 基类的纯虚成员函数 RunL()这是当来自异步服务提供者的完成事件发生时调用的事件处理函数活动调度器选择了一个活动对象处理该事件时,就调用这个函数RunL() 方法 这函数的名字有一定的误导性,因为异步函数已经在运行了 或许 HandleEventL() 或者

21、HandleCompletionL()这样的名字会更清楚的描述其功能活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.31事件处理RunL()的典型行为的典型行为 通过监测活动对象的 TRequestStatus 对象中的iStatus 即一个32位整形值,来判定异步请求是否成功完成RunL() 通常或者发送另一个请求或者告知系统中其他对象事件完成RunL() 的代码复杂程度可能变化很大一旦一旦RunL()开始执行开始执行它无法被其他活动对象的事件处理器所抢占正是由于这个原因代码应该尽快完成,这样其他事件才能够无延误的处理活动对象

22、Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.32 此图展示了当前活动对象向一个异步服务提供者提交一个请求,一段时间后请求完成了,产生一个事件,而事件被 RunL()处理时基本的动作执行序列 活动对象 异步服务提供者1. 提交请求并传递 iStatus3. 对自身调用SetActive()2. 设置 iStatus=KRequestPending 并开始服务4. 服务完成,服务提供者通过 RequestComplete() 来通知活动调度器,并传递一个完成结果5. 活动调度器对活动对象调用 RunL() 来处理该事件6. RunL()

23、 重新提交另一个请求,并且不可被抢占 活动规划器进程或线程边界进行服务处理事件处理活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.33撤销未完成的异步请求一个活动对象 必须能够撤销任何未完成的、自己所产生的非同步请求例如,活动对象所在的应用程序线程将要终止,他必须能够阻止请求CActive 基类 实现了一个 Cancel() 方法,该方法调用纯虚方法 DoCancel()然后等待请求尽早完成所有的 DoCancel() 实现都应该对异步服务提供者调用恰当的撤销函数活动对象Symbian OS基础Copyright 2001-20

24、07 Symbian Software Ltd.34撤销选定的异步请求DoCancel() 也可以包括其他处理 但它不应该异常退出或分配资源,而且也不应该执行长时间的操作限制该方法只执行撤销工作以及与与撤销关联的需要清除工作,而非实现复杂的功能,是一个很好的准则这是因为析构函数应该调用Cancel(),而可能已经清除了DoCancel() 函数所需要的资源不需要检查 .在调用 Cancel()之前,请求是否已经被被选中的这样做也是安全的,即便它当前不是活动的,例如正在等待事件活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.35错

25、误处理从Symbian OS v6.0 之后 活动对象提供了 RunError() 虚方法,当活动对象的RunL()方法中发生异常退出的时候,活动调度器会调用这个方法该方法接受一个异常退出码作为参数,返回一个错误码用以表明异常退出是否已经被处理了缺省的实现是不处理异常退出,而只是简单的返回传入函数的异常退出码如果活动对象能够处理 RunL()中发生的所有异常退出 它应该通过覆写缺省的实现CActive:RunError()来处理错误然后返回 KErrNone如果在RunL()中不会发生异常退出,则不必覆盖活动对象Symbian OS基础Copyright 2001-2007 Symbian S

26、oftware Ltd.36错误处理如果 RunError()返回非 KErrNone 的值,表明异常退出尚未解决那么活动调度器会调用它自己的 Error()函数来进行处理活动调度器 没有任何可用于执行错误处理的关于活动对象的上下文信息 因此,通常更倾向于在相应活动对象的 RunError() 方法中进行错误恢复活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.37析构活动对象CActive派生类的析构函数应该总是调用Cancel() 作为清除代码的一部分来终止选定的请求理想的情况是在活动对象持有的其他资源被销毁之前完成该调用,因

27、为这些资源可能会被服务提供者或者DoCancel() 方法所使用析构代码 应该释放对象持有的所有资源,包括所有异步服务提供者的句柄活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.38析构活动对象基类CActive的析构函数是虚函数对对象进行检查,确保活动对象当前不是活动的如果有任何请求被选定,即 Cancel() 没有被调用,那么将会发生致命错误该致命错误捕获所有导致它的程序设计错误 如一个请求在处理它的活动对象被销毁后完成了这会导致一个“迷失信号” (“stray signal” ),这时活动调度器无法找到一个活动对象来处理事

28、件再验证确认活动对象没有已提交的请求被选定后CActive 析构函数会将活动对象从活动调度器中移除活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.39活动对象类的示例下面的例子 描述了如何用活动对象包装异步服务 这个例子中采用的是 RTimer 服务提供的一个定时器Symbian OS 已经提供了一个抽象活动对象类 CTimer 该类包装了 RTimer ,并且可以继承该类但是,这里还是使用本例,因为它用简单明了的方式展示了如何写一个活动对象类下面的幻灯片 展示了涉及到的类以及它们和活动调度器的关系活动对象Symbian OS基

29、础Copyright 2001-2007 Symbian Software Ltd.40活动对象类的示例CActiveiActiveiStatusRunL()DoCancel()RunError()CExampleTimer NewL()After()RunL()DoCancel()RunError()CActiveSchedulerAdd(). RTimern1iTimerCExampleTimer 及其与 RTimer, CActive 和 CActiveScheduler之间的关系活动对象Symbian OS基础Copyright 2001-2007 Symbian Software L

30、td.41CExampleTimer 类class CExampleTimer : public CActive public: CExampleTimer(); static CExampleTimer* NewL(); void After(TTimeIntervalMicroSeconds32& aInterval);protected: CExampleTimer(); void ConstructL(); / 两阶段构造protected: virtual void RunL(); / 从CActive继承 virtual void DoCancel(); virtual T

31、Int RunError(TInt aError);private: RTimer iTimer; TTimeIntervalMicroSeconds32 iInterval; ;活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.42CExampleTimer 构造函数CExampleTimer:CExampleTimer() : CActive(EPriorityStandard) CActiveScheduler:Add(this); void CExampleTimer:ConstructL() User:LeaveIfEr

32、ror(iTimer.CreateLocal(); CExampleTimer* CExampleTimer:NewL() . CExampleTimer:CExampleTimer() Cancel(); iTimer.Close(); / 关闭句柄 创建异步服务提供者第二阶段构造,出于整洁,略去代码活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.43CExampleTimer:After()void CExampleTimer:After(TTimeIntervalMicroSeconds32& aInterval)

33、 if (IsActive() _LIT(KExampleTimerPanic, CExampleTimer); User:Panic(KExampleTimerPanic, KErrInUse); iInterval = aInterval; iTimer.After(iStatus, aInterval); SetActive(); 同时只允许提交一个定时器请求,调用者在提交另一个请求之前必须调用Cancel()设置 RTimer将该对象标志为活动的活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.44RunL() 和 DoC

34、ancel()void CExampleTimer:RunL() User:LeaveIfError(iStatus.Int(); _LIT(KTimerExpired, Timer Expiredn); RDebug:Print(KTimerExpired); iTimer.After(iStatus, iInterval); SetActive(); void CExampleTimer:DoCancel() iTimer.Cancel(); 事件处理方法如果发生错误就退出并且在 RunError()中处理错误否则, 标记完成时间提交计时请求 撤销定时器活动对象Symbian OS基础Co

35、pyright 2001-2007 Symbian Software Ltd.45错误处理和事件处理如果没有发生错误 事件处理者RunL() 使用RDebug:Print() 记录定时器完成情况作为调试输出RunL() 用存储的间隔值重新提交计时器请求一旦定时器请求已经开始,它将持续运行并且不断被提交直到活动对象调用Cancel()方法将其停止活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.46错误处理和事件处理事件处理者RunL()负责检查活动对象的iStatus 结果如果 iStatus 的值不是KErrNone 就异常退出

36、,这样RunError() 方法可以处理发生的问题在这种情况下 错误处理十分简单:从请求返回的错误被记录作为调试输出这可能在RunL() 方法中已经完成但是这被分离到了RunError() 方法中,用来演示如何使用活动对象框架将错误处理从时间处理的主逻辑中分离出来活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.47CExampleTimer:RunErrorTInt CExampleTimer:RunError(TInt aError) _LIT(KErrorLog, Timer error %d); RDebug:Print(

37、KErrorLog, aError); return (KErrNone); 该函数在 RunL()发生异常退出时被调用(aError 包含一个异常退出码)记录错误已被处理Symbian OS基础课程目标Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.48活动对象活动调度器了解活动调度器的角色和属性知道 CActiveScheduler:Start() 只能在至少有一个活动对象请求发出的时候之后才能被调用明白线程处理事件失败的典型的原因是可能是活动调度器没有启动或者过早的停止了理解 CActiveScheduler 可以称作继承,以及创

38、建一个派生活动调度器的原因活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.49建立和安装活动调度器绝大多数线程都有活动调度器它通常是由框架隐式创建的 (例如 GUI 框架中的CONE) 服务器代码必须在使用活动对象之前显示创建并启动一个活动调度器 基于控制台的测试代码如果依赖了一些使用活动对象的组件,必须在其主线程中创建一个活动调度器活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.50建立和安装活动调度器建立和安装活动调度器的代码:CActiveScheduler

39、* scheduler = new(ELeave) CActiveScheduler;CleanupStack:PushL(scheduler);CActiveScheduler:Install(scheduler);活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.51启动活动调度器一旦活动调度器被建立并且安装完毕后,它的事件处理的循环等待功能将通过调用静态CActiveScheduler:Start() 启动但是调用Start() 进入事件处理循环后,只有在调用CActiveScheduler:Stop() 的时候才会返回在活

40、动调度器启动之前,必须至少有一个活动对象发出的异步请求这样,线程的请求信号量被标识并调用User:WaitForAnyRequest()来完成如果没有请求发出,线程只是简单的进入循环等待状态并且不定时的休眠活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.52活动调度器等待循环当异步请求完成时当服务提供者和服务请求者在同一个线程中的时候,异步服务提供者调用User:RequestComplete()方法当它们不在同一个线程中的时候,调用 RThread:RequestComplete() 方法它传递给RequestComplete

41、()与请求关联的TRequestStatus一个完成结果典型的标准错误代码,如 KErrNone 或者 KErrNotFound RequestComplete() 将TRequestStatus 值设定为给定的错误代码在请求线程中产生一个完成,通过标志线程的请求信号量活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.53活动调度器等待循环当请求已经发出,请求线程将在活动调度器的事件处理循环中运行当它没有处理其他的完成事,活动调度器通过调用User:WaitForAnyRequest()挂起线程该函数将等待线程的请求信号量的标记信

42、号活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.54活动调度器等待循环当收到信号时活动调度器决定哪个活动对象来处理该事件它检查活动对象的优先级列表,然后决定标记哪个请求即,把他的iActive 的布尔值设为ETrue (在请求被提交并且调用 CActive:SetActive() 之后设定)活动调度器检查活动对象的TRequestStatus 成员数据,来确定是否设置了一个除KRequestPending之外值指明活动对象与一个已经完成的请求关联,并且应该调用其事件处理代码活动对象Symbian OS基础Copyright 2

43、001-2007 Symbian Software Ltd.55活动调度器等待循环找到合适的活动对象活动调度器清除活动对象的iActive 布尔标记,并且调用RunL() 进行事件处理RunL() 处理事件进行必要的处理 它也可能提交一个请求或者在另一个系统中生成一个对象注意: 在运行的时候可能产生另一个事件的请求,但是RunL() 不能被抢占RunL() 完成 活动调度器恢复控制权然后决定是否有其他请求已经完成活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.56活动调度器等待循环一旦 RunL()完成后活动调度器通过调用Use

44、r:WaitForAnyRequest()重新进入事件处理等待循环User:WaitForAnyRequest() 检查线程的请求信号量 没有线程请求完成: 挂起它如果在以前的RunL()还在还在运行时,信号量指出另一个事件已经发生:则立刻返回,重复活动对象查找和错误处理活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.57活动调度器等待循环EventProcessingLoop() User:WaitForAnyRequest(); FOREVER if (activeObject-IsActive()& ActiveO

45、bject-iStatus!=KRequestPending) activeObject-iActive = EFalse; TRAPD(r, activeObject-RunL(); if (KErrNone!=r) r = activeObject-RunError(); if (KErrNone!=r) Error(r); break; 挂起线程直到事件发生从优先级列表中取得下一个活动对象 并且事件的 iStatus!=KRequestPending找到一个已准备好处理事件的活动对象重置 iActive 状态以表明其不再活动在TRAP中调用活动对象的事件处理事件处理函数异常退出,调用Ru

46、nError() 不使用objectRunError()处理错误调用CActiveScheduler:Error() 事件处理完毕,跳出查找循环并在FOREVER 循环结束处恢复执行1. 当请求信号亮被通知的时候,线程将苏醒2. 按照优先级降序的顺序检查调度器器中每一个活动对象3. 调用第一个活动且已完成的活动对象的事件处理函数事件处理循环伪代码 活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.58停止活动调度器活动调度器停止 通过调用 CActiveScheduler:Stop(), 通常在RunL()中调用当调用CActiv

47、eScheduler:Stop()方法完成,即返回时对CActiveScheduler:Start() 的调用也返回停止活动调度器 终端线程中的事件处理它只应被控制线程的主活动对象调用因此在 GUI 应用中不要这么做活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.59扩展活动调度器CActiveScheduler 是一个具体的类 它可以用于 “就是” ,也可以被继承它定义了两个可扩展的虚函数:Error() 和WaitForAnyRequest()默认情况下WaitForAnyRequest()函数只是简单的调用User:Wai

48、tForAnyRequest()但它可以被扩展,例如在等待之前或之后执行一些处理 如果函数被覆盖,它必须要么就必须调用基类函数或者直接调用 User:WaitForAnyRequest()活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.60扩展活动调度器如果在 RunL() 事件处理函数中发生异常退出活动调度器把错误码传递给RunError()方法 如果 RunError() 方法无法处理异常退出 它将返回错误码并且活动调度器将其传递给自己的Error() 方法默认的 Error() 抛出致命错误E32USER-CBASE 47

49、 但可以被覆盖以处理错误例如,通过调用错误解析器来获得错误的文本描述,并将这些内容显示给用户或写入日志文件中活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.61警告如果活动对象代码 依靠特殊的活动调度器的特殊版本那么就无法移植这些代码使其能运行在其他由更基础的活动调度器管理的线程中此外 为了扩展活动调度器而添加的代码应该简单易懂并且要避免执行复杂或者缓慢的处理而妨碍整个线程的事件处理活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.62没有活动调度器的线程有一些线程

50、有意的不使用活动调度器,因此它不能使用活动对象或者由活动对象组成的组件Java实现 不支持活动调度器Java 的本地方法不能使用活动对象.C 标准库 (STDLIB)线程是没有活动调度器的,因此标准库代码不能使用活动对象。但表准库代码可被活动对象所使用,例如在初始化代码中或者在RunL() 中OPL不支持活动调度器,并且OPL的C+扩展 (OPXs) 绝不能使用活动对象或者那些使用活动对象的组件OPL 是一个解释性语言,使用入门级的开发工具,可以进行快速应用开发活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.63活动对象取消已发

51、出的请求理解活动对象在正常完成异步请求以及调用Cancel()结束时,代码中的不同路径活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.64CActive:Cancel() 调用 DoCancel()的基类DoCancel() 不能发生异常退出或进行资源分配,因为它将被析构函数调用活动对象内部绝不可以直接调用 DoCancel() 方法来撤销一个请求应该通过调用 CActive:Cancel()来调用DoCancel() 并且处理取消事件,详见下一页描述CActive:Cancel()活动对象Symbian OS基础Copyrig

52、ht 2001-2007 Symbian Software Ltd.65撤销一个已发出的请求当调用 CActive:Cancel()时发生了什么?首先检查调用它的活动对象是否有标记过的请求这通过检查iActive 标记是否通过调用CActive:IsActive()函数来设置过活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.66撤销一个已发出的请求如果活动对象确有已发出的请求 CActive:Cancel() 调用 DoCancel() CActive类中的纯虚函数 必须在活动对象类中实现 实现 DoCancel() 时不需要有

53、代码来检查是否有发出的请求因为如果没有发出的请求,DoCancel() 不会被调用通过调用其提供的撤销方法, DoCancel()必须发送给撤销封装的异步服务提供者的请求活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.67撤销一个已发出的请求调用了 DoCancel()以后CActive:Cancel() 然后调用 User:WaitForRequest() 传递关于他的 iStatus成员变量CActive:Cancel() 是一个同步函数 直到DoCancel()返回并且原来的异步请求完成时它才会返回。 因此:DoCance

54、l() 不应该执行长操作线程被阻塞直到异步服务提供者发布一个取消通知,即将 iStatus设置为KErrCancelCActive:Cancel() 重置活动对象的iActive 成员,以显示不再有已发出的请求了活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.68撤销一个被发出的请求撤销事件 由活动对象的Cancel()方法处理,而不是由活动调度器处理RunL() 不会被调用CActive:Cancel() 方法执行所有普遍的撤销代码一个派生活动对象类只用DoCancel() 来调用异步服务提供者的适当的撤销函数并且执行必要的清

55、除操作 DoCancel() 不可以调用 User:WaitForRequest() 这将使得线程的信号量计数变得混乱活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.69信号迷失的致命错误当一个活动对象要被销毁的时候,必须确保没有等待完成的需要处理的事件这是因为CActive的析构函数把活动对象从活动规划器列表中删掉了如果任何标记的请求要在过一段时间才能完成的时候进行销毁,将会产生一个活动对象失去关联的事件这将导致迷信号的致命错误 活动对象Symbian OS基础Copyright 2001-2007 Symbian Softw

56、are Ltd.70CActive:CActive()避免信号迷失错误 在把活动对象从活动调度器删除的之前,基类CActive 的析构函数应检查没有标记的请求要强调这个问题,将抛出一个 E32USERCBASE 40 致命错误这个致命错误比迷失信号的致命错误更容易跟踪鉴于这个原因, Cancel()应该在每个继承自活动对象类的对象中被调用活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.71活动对象后台任务理解如何使用活动对象来完成长任务(或者说是后台任务)理解如何实现自我完成(self-completion)活动对象Symbia

57、n OS基础Copyright 2001-2007 Symbian Software Ltd.72后台任务除了封装异步服务提供者活动对象也可以用来实现长任务,这种任务需要在低优先级的后台中运行任务必须能分割为若干小的片段 例如,为打印准备数据,执行后台重算和压缩数据 这些都要在活动对象的事件处理方法中执行它们必须足够短,因为RunL()一旦运行就无法被抢占活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.73后台任务活动对象应被赋予一个低优先级 诸如 CActive:TPriority:EPriorityIdle (=-100)

58、决定了任务片段只在没有其他事件要处理的时候才运行 也就是通常所说的间歇运行 如果任务由一系列不同的步骤组成活动对象必须跟踪运行的一系列状态使用状态机实现活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.74后台任务活动对象 活动对象通过产生自己的事件来调用自己的事件处理函数,从而可以驱动任务不再调用异步服务提供者,只是活动对象对自己的iStatus 对象调用User:RequestComplete()这样活动对象就将调用它的事件处理函数这样的话,活动对象就会不断提交请求,直到整个任务完成活动对象Symbian OS基础Copyri

59、ght 2001-2007 Symbian Software Ltd.75后台任务示例代码中展示的是一个典型的例子 在类声明中展示了所有相关方法 但只给出了和这里的讨论相关的实现为了简洁,这里省略了错误处理StartTask(), DoTaskStep()和 EndTask() 执行小的、不连续的任务,可以直接被低优先级活动对象中的RunL()方法所直接调用活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.76后台任务: CLongRunningCalculationclass CLongRunningCalculation :

60、public CBase public: static CLongRunningCalculation* NewL(); TBool StartTask(); TBool DoTaskStep(); void EndTask(); . ;TBool CLongRunningCalculation:DoTaskStep() . . . . 在任务执行前初始化执行一个短小的任务步骤销毁中间数据 执行一个尖酸的任务步骤,如果还有任务要做则返回 ETrue, 如果任务完成了 ,要返回 EFalse 略去活动对象Symbian OS基础Copyright 2001-2007 Symbian Software Ltd.77后台任务: CBackgroundRecalc

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论