随笔 - 2, 文章 - 73, 评论 - 60, 引用 - 0
数据加载中……

S60的多线程,活动对象,活动规划器,异步函数

        Symbian也是多任务操作系统,当然也要用进程、线程完成多任务处理。进程是程序的运行实例,有自己独立的数据空间。线程是进程的执行单元,一个进程至少有一个主线程。多线程可以并发运行采用抢占式完成多任务处理。但是Symbian下不提倡使用多线程,因为Symbian系统是通过客户端/服务器结构来提供对线程资源的访问,这就意味着访问线程需要与内核的服务器程序不断地进行通信,效率低。      
        在单线程内,配合使用活动对象+异步函数,完全可以模拟多线程并行运行。不同的是,这是一种非抢占式并行运行,即当前活动对象结束之前,其它活动对象不能运行。       异步函数在执行后立即返回,继续执行它下面的代码。异步操作有后台继续执行,结束后通过信号量表示异步操作结束。同步函数必须函数内所有操作全部执行结束后才能返回,执行下面的代码,否则就阻塞在那里。很显然,实现多任务并行运行必须使用异步函数。      
        活动对象是CActive的派生类,设立它的作用就是为了提供一个专门用来调用异步函数的类。因为这个类中专门设有回调函数,使异步函数结束后,能利用这个回调函数进行尾处理。这个函数就是RunL()。在活动对象外面使用异步函数,只能截获信号量,不能直接进入某个回调函数。
       异步函数结束后,是如何进入到正确的回调函数中的呢?系统运行着一个活动调度器(CActiveSchedule),它能截获异步函数结束后发出的信号量,并根据这个信号量,调用相应的RunL()。问题是如果CActiveSchedule截获了这个信号,但却找不到该调哪个活动对象的RunL()怎么办?这时CActiveSchedule会抛出异常,这种状态叫信号游离,这种状况经常发生,所以使用活动对象应该避免这种情况发生。
       哪些情况会产生游离信号?理解这个问题首先要了解CActiveSchedule如何判断这个信号是不是游离信号。CActiveSchedule判断游离信号的条件是
 for(I=0;I<NUMBERS_OF_ACTIVE_OBJECT;I++)
{
      IF(ACTIVE_OBJECTS[I].iActive==ETrue&&ACTIVE_OBJECTS[I].iStatus!=KRequestPending)      
      {     
       //由此可见,规则有二
       //规则1 根本就没有这个活动对象
       //规则2 活动对象不是“活”的 ACTIVE_OBJECTS[I].RunL();
      }
}
所以有如下情况可能会导致出现游离信号出现
1.没有调用CActiveSchedule::Add(this);把活动对象加到活动调度器中。
2.没有调用SetActive把活动对象激活。破坏规则(2)
3.在活动对象外调用异步函数后,没有用User::WaitForRequest()截获异步函数完成信号量。信号量进入循环却找不到活动对象,破坏规则1。
4.同时一个活动对象中同时调用两个异步函数。如:InvokeAsyncFunc1();SetActice();InvokeAsyncFunc2();SetActive();第一个异步函数结束后,执行完回调函数RunL()后,会把iActive置为EFalse,这时第二异步函数的结束信号进入时,却发现活动对象不是“活”的,破坏规则2。所以在一个活动对象不能同时调用多个异步函数。

posted on 2007-10-14 22:02 郭天文 阅读(2283) 评论(1)  编辑 收藏 引用 所属分类: S60

评论

# re: S60的多线程,活动对象,活动规划器,异步函数  回复  更多评论   

在单线程内,配合使用活动对象+异步函数,完全可以模拟多线程并行运行。不同的是,这是一种非抢占式并行运行,即当前活动对象结束之前,其它活动对象不能运行。
--------------------------------------------
楼主好,我想实现弹出一个RNotifier后用户在一定时间内没有点软键来对RNotifier做出响应,这个RNotifier自动消失。但是搞了好久都没有做出来。
看了楼主以上文字,是不是因为两个活动对象嵌套运行的缘故导致无法实现?

我原本的思路如下:
在一个CTimer派生类中,
ConstructL()
{
CTimer::ConstructL();
After(TTimeIntervalMicroSeconds32(3000000)); //等待3秒钟
...
RNotifier notifier;
TRequestStatus status;
notifier.Connect ();
notifier.Notify(...,status);
User::WaitForRequest (status);
{
//根据status进行相应处理
}
}

RunL()
{
//如果notifier还在,干掉它
}

但是notifier.Notify(...,status);这行运行后,Notifier弹出来等待用户确认,一直不操作的话,RunL()一直调不到,直到按软键结束Notifier后RunL()才调到。


2007-11-26 14:59 | newbie

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理