活动对象-同步调用

一、使用CActiveSchedulerWait类

 

        很多初学者在开始时会将CActiveScheduler和CActiveSchedulerWait类弄混,CActiveScheduler是活动对 象的调度器,而CActiveSchedulerWait可以简单的理解为一个当 前 线程的阻塞器

  • 调用CActiveSchedulerWait::Start()方法时,线程阻塞;
  • 调用CActiveSchedulerWait::AsyncStop()方法时,请求停止对线程的阻塞

        因此,我们在不修改原来活动对象代码的情况下,只要简单的在异步函数调用方法后加上"CActiveSchedulerWait::Start()",在 活动对象的RunL方法的开头加入"CActiveSchedulerWait::AnsycStop()"就可以了。

        针对上一节教程介绍的控制台应用程序,我们对以下几个方法(下划线为修改部分)进行修改:

 

点击此处下载源代码

 

CActiveSchedulerWait * iWait ;

 

void CMyActiveObject::ConstructL ()

    {

    User :: LeaveIfError ( iTimer . CreateLocal () ); // Initialize timer

    CActiveScheduler :: Add ( this ); // Add to scheduler

 

    iWait = new ( ELeave ) CActiveSchedulerWait ;

    }

 

CMyActiveObject::~CMyActiveObject ()

    {

    Cancel (); // Cancel any request, if outstanding

    iTimer . Close (); // Destroy the RTimer object

    // Delete instance variables if any

 

    if ( iWait -> IsStarted ())

        {

        iWait -> AsyncStop ();

        }

 

    delete iWait ;

    iWait = NULL;

    }

 

void CMyActiveObject::StartL ( TTimeIntervalMicroSeconds32 aDelay)

    {

    Cancel (); // Cancel any request, just to be sure

 

    iTimer . After ( iStatus , aDelay); // Set for later

    SetActive (); // Tell scheduler a request is active

 

    iWait -> Start (); // 1

    }

 

void CMyActiveObject::RunL ()

    {

    iWait -> AsyncStop (); // 2

 

    TBuf<50> outputStr;

    outputStr. AppendNum ( iCount );

    iConsole . Write (outputStr);

    iConsole . Write (_L( "/n" ));

    iCount ++;

    }

 

    使用CActiveSchedulerWait的几点注意事项:

  1. CActiveSchedulerWait必须结合活动对象使用,而且使用方法只有以上代码介绍的那一种;
  2. Start方法和AsyncStop方法必须成对出现;
  3. 程序退出时要检查CActiveSchedulerWait是否在IsStarted()状态,如果是则调用AsyncStop方法。否则程序不 能正常退出;
  4. CActiveScheduler类内部有自己的静态指针,提供的静态方法都调用了内部的静态指针。而CActiveSchedulerWait 类没有内部静态指针,方法也不是静态的,我们必须自己管理CActiveSchedulerWait类的全局指针,在这点上程序要经过良好的设计。

 

二、使用User::WaitForRequest方法

    如果不想使用活动对象,也不想使用难于管理的CactiveSchedulerWait,你可以使用User::WaitForRequest方法。以下 是User::WaitForRequest方法的原型:

IMPORT_C static void WaitForRequest ( TRequestStatus & aStatus);

        此方法将等待异步函数服务器返回的信号量,然后匹配aStatus参数。如果接收到的信号与参数aStatus一一匹配,则跳过阻塞进入下一行代码,否则 继续阻塞线程直到aStatus对应的信号通知返回。

User::WaitForRequest还有一个重载的方法,它可以监视两个信号的通知:

IMPORT_C static void WaitForRequest ( TRequestStatus & aStatus1, TRequestStatus & aStatus2);

         有了User::WaitForRequest,异步函数使用起来就变得非常方便,我们不需要创建活动对象,也不需要创建成员变量 TRequestStatus,只需要声明局部的TRequestStatus、局部的异步函数类,在异步函数调用之后,加入 User::WaitForRequest(status),就能够使线程阻塞在User::WaitForRequest处直到status对应的异步 函数处理完成。

LOCAL_C void DoTestL ()

    {

    RTimer timer;

    CleanupClosePushL(timer);

    User :: LeaveIfError (timer. CreateLocal ());

   

    TRequestStatus status(KRequestPending);

   

    // 调用异步方法并将 status 传入

    timer. After (status, 1000000);

   

    // 等待 status 对应的信号量,此处用了 User::WaitForRequest 方法将异步方法的调用模拟成同步

    User :: WaitForRequest (status);

    CleanupStack :: Pop (&timer);

    }

 

LOCAL_C void MainL ()

    {

    TInt n = 0;

    TBuf<10> str;

    _LIT(KNewLine, "/n" );

   

    FOREVER

        {

        DoTestL();

        str. Num (n);

        n++;

       

        console-> Write (str);

        console-> Write (KNewLine);

        }

    }

 

三、使用User::WaitForRequest方法的问题

        User::WaitForRequest有时候不会正常运行,如:CImageDecoder::Convert方法:

IMPORT_C virtual void Convert ( TRequestStatus * aRequestStatus, CFbsBitmap & aDestination, CFbsBitmap & aDestinationMask, TInt aFrameNumber = 0);

        最后一个参数必须为EOptionAlwaysThread,User::WaitForRequest才能正常执行,个人认为 CImageDecoder::Convert如果没有加EOptionAlwaysThread参数的时候是使用"长线任务"(将在下一节介绍)实现 的。所以,CImageDecoder::Convert方法应该按照如下方法调用:

    TRequestStatus status(KRequestPending);

    CImageDecoder * decoder = CImageDecoder::FileNewL ( iFs , aFileName, KMIMEType );

   

    decoder-> Convert (&status, aBitmap, CImageDecoder :: EOptionAlwaysThread );

    User :: WaitForRequest (status);

   

    delete decoder;

    decoder = NULL;

 

四、小结

        本文介绍了在如果将异步函数同步使用。其实在Symbian的早期编程中还有一种异步函数的同步方法,那就是在异步函数调用后使用 CActiveScheduler::Start()方法。但是这种方法已经被Symbian 7.0后的CActiveSchedulerWait替代,在此处就不再介绍。在下一节里将介绍活动对象的长线任务(Long- Running Task)

        另:在介绍活动对象的专题里涉及到很多Symbian OS的客户/服务器架构的知识,我会在近期另外开一个专题讲解,请大家耐心等待。

 

其他:

CActiveSchedulerWait::Start()

CActiveSchedulerWait:: AsyncStop()

也可以完成这样的功能.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值