﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-天道酬勤-文章分类-symbian 学习</title><link>http://www.cppblog.com/pcyang2008/category/10625.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 23 May 2009 15:40:53 GMT</lastBuildDate><pubDate>Sat, 23 May 2009 15:40:53 GMT</pubDate><ttl>60</ttl><item><title>Symbian编程总结-基础篇-活动对象正解（2）-使用活动对象(转)</title><link>http://www.cppblog.com/pcyang2008/articles/85546.html</link><dc:creator>程程</dc:creator><author>程程</author><pubDate>Sat, 23 May 2009 14:37:00 GMT</pubDate><guid>http://www.cppblog.com/pcyang2008/articles/85546.html</guid><wfw:comment>http://www.cppblog.com/pcyang2008/comments/85546.html</wfw:comment><comments>http://www.cppblog.com/pcyang2008/articles/85546.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/pcyang2008/comments/commentRss/85546.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/pcyang2008/services/trackbacks/85546.html</trackback:ping><description><![CDATA[一、活动对象工作流程
<p>　　首先我们用时序图来说明一下应用程序、活动对象、活动调度器及异步函数服务器之间创建及调用的流程：</p>
<p><img onclick=get_larger(this) alt=Symbian编程总结-基础篇-活动对象正解（3）-活动对象的工作原理 src="http://img.ddvip.com/2008_11_24/1227495212_ddvip_6027.png"> </p>
<p>　　下面我们针对每一个步骤结合代码（点击此处下载代码）进行说明：</p>
<p>　　1、创建并安装活动调度器：</p>
<p><code>CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();<br>　　CleanupStack::PushL(scheduler);<br>　　CActiveScheduler::Install(scheduler);</code></p>
<p>　　如果创建了一个基于GUI应用程序框架的应用程序，框架已经为我们创建并且安装了活动调度器，我们可以直接使用CActiveScheduler的一系列方法。</p>
<p>　　2、创建活动对象</p>
<p><code>iMyAO = CMyActiveObject::NewL(*console);</code></p>
<p>　　此处创建的CMyActiveObject类是继承自CActive类的活动对象。</p>
<p>　　3、将活动对象添加到活动调度器中</p>
<p><code>void CMyActiveObject::ConstructL()<br>　　{<br>　　....<br>　　CActiveScheduler::Add( this); // Add to scheduler<br>　　}</code></p>
<p>　　可以看到，活动对象在通过&#8220;二阶段构造&#8221;创建时就已经将自己的指针添加到了活动调度器中。</p>
<p>　　4、StartL</p>
<p>　　StartL为应用程序请求活动对象调用异步函数的方法，此处用户可以根据自身需求对此方法重新命名：</p>
<p>&#160;</p>
<p><code>void CMyActiveObject::StartL(TTimeIntervalMicroSeconds32 aDelay)<br>　　{<br>　　Cancel(); // 取消异步函数请求<br>　　iStatus = KRequestPending;<br>　　iTimer.After(iStatus, aDelay); // 在此处调用异步函数<br>　　SetActive(); // 将成员变量iActive = ETrue<br>　　}</code></p>
<p>　　因为不能保证用户在等待异步函数调用完毕返回的时候不重新调用StartL方法，所以在StartL方法的入口点首先调用Cancel()方法取消异步请求，否则可能会发生臭名远扬的&#8220;信号迷失&#8221;错误。</p>
<p>　　5、iStatus = KRequestPending</p>
<p>　　在以上代码StartL方法中，异步函数调用之前，首先要将iStatus设置为KRequestPending以便活动调度器遍历时匹配。</p>
<p>　　6、请求异步函数并发送iStatus</p>
<p>　　在StartL方法中，iTimer.After(iStatus, aDelay);这行代码传递了成员变量的引用并调用了异步函数iTimer.After。</p>
<p>　　7、SetActive</p>
<p>　　调用基类CActive的SetActive方法，方法内部将iActive设置成ETrue，以便活动调度器遍历时匹配。</p>
<p>　　8、启动活动调度器</p>
<p><code>CActiveScheduler::Start();</code></p>
<p>　　10、查找对应的活动对象</p>
<p>　　我们在上一节已经通过分析并还原了CActiveScheduler::Start()方法的伪代码，此代码块在另外一个线程遍历所有向调度器注册的活动对象，查看对象的iStatus不为KRequestPending且iActive为ETrue。因为异步函数服务器完成了请求的工作以后，会改变iStatus的实参，使其不等于KRequestPending，再加上活动对象在调用完异步函数返回后马上改变了iActive值为ETrue，所以活动调度器只要判断iStatus != KRequestPending &amp;&amp; iActive == ETrue则可以知道那一个活动对象所请求的异步服务已经完成。</p>
<p>&#160;</p>
<p>　　9、WaitForAnyRequest()等待异步函数返回通知，11、RequestComplete()并将iStatus的值改变</p>
<p>　　当异步服务已经完成了所请求的工作，它会使用User::RequestComplete()发送一个通知，活动调度器会通过User::WaitForAnyRequest()或RThread::WaitForAnyRequest()收到这个通知，随后遍历向其注册的条件匹配的活动对象（第8点下划线部分说明）。</p>
<p>　　12、调用RunL方法</p>
<p>　　如果找到了异步函数所对应的活动对象，则调用活动对象的RunL方法，RunL方法在TRAP宏里运行。如果RunL方法抛出异常，活动调度器会自动调用活动对象的RunError方法。因此大多数情况下不需要在RunL内编写异常捕获的代码。</p>
<p>　　活动对象调用完RunL方法后，将活动对象的iActive值设置为EFalse，以便在下次遍历集合时跳过已经处理过的活动对象。</p>
<p>　　如果没有找到异步函数所对应的活动对象，活动调度器将抛出一个&#8220;信号迷失&#8221;异常。</p>
<p>　　13、CActiveScheduler::Stop()</p>
<p>　　停止活动调度器，停止监控异步函数返回的信号。</p>
<p>　　二、活动对象专属错误-&#8220;信号迷失&#8221;</p>
<p>　　从上面的分析我们知道，活动调度器会拦截异步函数返回的消息，随后遍历活动对象集合找到相应的活动对象调用，如果没有找到则抛出&#8220;信号迷失&#8221;异常。有以下两种方法会导致&#8220;找不到活动对象&#8221;的发生：</p>
<p>　　活动对象根本没有注册到活动调度器中：没有调用CActiveScheduler::Add方法注册活动对象 </p>
<p>　　不满足活动调度器查找活动对象的标准iStatus != KRequestPending &amp;&amp; iActive == ETrue：在调用异步函数后，没有调用SetActive()方法将iActive的值设为ETrue；或者将iStatus同时传给两个异步函数，导致第二个异步函数返回时，当前活动对象的iActive为EFalse，调度器找不到相应的活动对象。 </p>
<img src ="http://www.cppblog.com/pcyang2008/aggbug/85546.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/pcyang2008/" target="_blank">程程</a> 2009-05-23 22:37 <a href="http://www.cppblog.com/pcyang2008/articles/85546.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>