ActiveObject 在symbian里是一个很重要的概念
应该说所有的Symbian程序都是运行在一个或多个 ActiveObject里面。

大多数Symbian的程序的入口几乎都是这样的,除了少数Console程序以外
GLDEF_C TInt E32Main()
{
 return EikStart::RunApplication( NewApplication );
}

如果你有机会调试并跟踪到Symbian的源代码里面,你会发现EikStart::RunApplication会调用
CActiveScheduler::Start()

这个调用意味着启动了一个 Scheduler 也就意味着进入了 ActiveScheduler的循环。

程序运行进入CActiveScheduler::Start()之后就不会出来了,直到程序结束。

这似乎很象什么?对了,象windows的消息循环!

while(getmessage(...))
{
 TranslateMessage(...);
 DispatchMessage(...);
}

除非程序退出,否则会一直运行在这样的死循环里面。

Scheduler::Start里面也是类似的代码,做着类似的事情
1。等待事件
2。找一个合适的对象来处理事件
3。然 后继续等待事件,直到得到一个退出的事件。

但是和windows的消息循环不一样的地方在于,Scheduler 里面调度的不是窗口
而是一个个 ActiveObject,Scheduler获得了一个事件后,就会找一个合适的ActiveObject去处理事件

所有的ActiveObject在创建后会通过CActiveScheduler::Add 把自己加入到Scheduler里面。

这套模式又使我想起了什么,对了,是ACE--那个网络程序的framework,ACE中也是类似的模式
不过Scheduler叫做 Reactor。
不过ActiveObject叫做Task。

本质上讲,这就是一套用单线程通过事件驱动,来模拟多任务的设计模式。
每个ActiveObject是独立的,多个ActiveOject 看似是并行的,实际上却是运行在一个线程里。

不同的是ACE里面的 Reactor 是可以多线程的,可以用一个线程池来同时执行多个 Task。

在symbian的世界里,设备的资源都很有限,内存小,CPU也慢,所以开一个线程开销比较大,ActiveObject有效的
代替了部 分多线程的功能。

编写ActiveObject还是比较简单的,所有的ActiveObject都是从CActive派生的。
其中RunL、 DoCancel 是必须重载的虚函数,每次有事件发生Scheduler就会调用RunL
那么如果有多个ActiveObject存在,那么事 件发生了Scheduler怎么才能知道该调用哪个ActiveObject呢?

很简单,每个ActiveObject都有一个iStatus成员,每个事件发生器都会指定一个iStatus,Scheduler会调用
iStatus 对应的那个ActiveObject。

比如最简单事件发生器,RTimer,他的作用是在指定的时间后产生一个事件,起到定时器的作用
用法如下
RTimer t;
t.After(iStatus, 1000000);

上面的语句表示在1秒钟后 产生事件,这个事件将由iStatus对应的ActiveObject来响应。(Symbian系统下 时间单位是 1/1000000 秒,而不是1/1000秒)