Active Object是Symbian中的一个重要概念,它是Symbian OS为了节省系统资源利用单线程来实现多任务异步处理的机制。
S60本身的Framwork也大量采用AO进行多任务的实现,例如我们可以在S60 EIKON Control based application中直接调用以下代码添加自身的AO到系统CActiveScheduler中。
void CActiveTest3NewClass::ConstructL()
{
User::LeaveIfError(iTimer.CreateLocal()); // Initialize timer
CActiveScheduler::Add(this); // Add to scheduler
}
使用Carbide C++ 1.3,通过模板向导生成的控制台程序自动为我们生成了创建活动调度器的代码:
CActiveScheduler* scheduler = new (ELeave) CActiveScheduler(); CActiveScheduler::Install(scheduler);CActiveScheduler::Install()方法调用以后,内 部代码就会将scheduler指针赋值给CActiveScheduler类内部的静态指针,后面的代码就可以方便的使用 CActiveScheduler类的静态方法。
如果你有CustKit、DevKit或者BAK,那么跟踪Symbian程序的入口
GLDEF_C TInt E32Main()
{
return EikStart::RunApplication( NewApplication );
}
你会发现EikStart::RunApplication其实调用的就是CActiveScheduler::Start(),这个调用启动了一个 CActiveScheduler并进入了CActiveScheduler的循环。而程序一旦进入了CActiveScheduler的循环后就不会跳 出来,直到程序结束。
这一点很像Windows的消息循环机制:
while(getMessage(...))
{
TranslateMessage(...);
DispatchMessage(...);
}
CActiveScheduler维护着一个等待循环,这个等待循环用于接受所有活动对象发出的请求,然后交给相应的服务器程序进行处理。当请求得到响应 后,服务器会产生一个事件,这个事件由RunL()函数处理,事件处理完后RunL()函数可以决定是继续发送下一个请求还是终止发出请求。
好了,当我们需要AO同步操作的时候怎么办?Symbian提供了一个对象叫CActiveSchedulerWait,使用这个类,可以将AO转成同步操作,具体用法如下:
首先,程序调用SetActive(),这时AO被激活,schedual将调度这个AO,但此时如果接着调用Wait()的话,代码就会进行等待,直到 RunL函数被调度执行,我们可以再RunL函数里面使用AsyncStop()使代码停止等待。当然,析构函数里面要检测 CActiveSchedulerWait的状态,如果在等待则停掉,是不是很不错?
值得注意的是,CActiveSchedulerWait并没有阻塞线程,那么,CActiveSchedulerWait是怎么做到的?我猜 测,CActiveSchedulerWait其实就是一个接收特定消息的模态窗口,里面也实现了一个消息循环,所以可以做到阻塞代码而不阻塞线程。