【原创】Symbian平台移植之——活动规划器CActiveScheduler的灵活应用

来源:互联网 发布:免费视频剪辑软件app 编辑:程序博客网 时间:2024/06/03 18:17

    由于做工程的移植工作,需要移植代码到Symbian平台上,但之前代码的架构与Symbian平台看起来是有冲突,体现在之前代码中有一个独立线程用来做事件驱动、分发,然后在事件回调中完成自己的逻辑(包括异步请求),该线程是用

    while(1)

    {

        getevent();

        dispatchevent()

    }

来实现。但在Symbian平台上,所有的异步方法的侦测是通过CActiveScheduler.Start()完成,且该方法实际上就是一个死循环。这样看起来,在同一个线程中,是不可能有两个死循环存在的,这个移植是不能完成的,除非修改代码架构。

    这个问题确实困扰了很久,呵呵,因为是一个人开发,确实没有人可以帮忙出点主义,脑子也死了,想不开了。现在终于有眉目了,基本可以解决该问题,途径就是理解活动对象和活动规划器的原理,灵活应用这对活宝!

    之前一直想着,为了能侦测到异步请求是否完成,CActiveScheduler.Start()这个方法必须在线程的初始就调用,其实可以不这样,CActiveScheduler.Start()在线程的任何地方随时可以调用,且CActiveScheduler起来后,还是可以侦测到“很久”以前就完成的异步请求。例子如下:

 

/*  ============================================================================

 Name  : NewClassTest.h  Author   : Alex  Version  : 1.0  Copyright   : su-fun  Description : CNewClassTest declaration  ============================================================================  */

 

#ifndef NEWCLASSTEST_H

#define NEWCLASSTEST_H

#include <e32base.h> 

// For CActive, link against: euser.lib

#include <e32std.h>  

//For RTimer, link against: euser.lib

 

class CNewClassTest : public CActive

{

public:  

    // Cancel and destroy  

    ~CNewClassTest();

     // Two-phased constructor.  

    static CNewClassTest* NewL();

     // Two-phased constructor.  

    static CNewClassTest* NewLC();

 

public:  

    // New functions  

    // Function for making the initial request  

    void StartL(TInt aState, TTimeIntervalMicroSeconds32 aDelay);

 

private:  

    // C++ constructor

    CNewClassTest();

     // Second-phase constructor  

    void ConstructL();

 

private:  

    // From CActive  // Handle completion  

    void RunL();

    // How to cancel me  

    void DoCancel();

     // Override to handle leaves from RunL(). Default implementation causes  

    // the active scheduler to panic.  

    TInt RunError(TInt aError);

 

public:  

    enum TNewClassTestState  

    {   

        EUninitialized=12, // Uninitialized   

        EInitialized=22, // Initalized   

        EError=32 // Error condition  

    };

 

private:  

    TInt iState; // State of the active object  

    RTimer iTimer; // Provides async timing service

};

 

#endif // NEWCLASSTEST_H

 

/*  ============================================================================  

Name  : NewClassTest.cpp  Author   : Alex  Version  : 1.0  Copyright   : su-fun  Description : CNewClassTest implementation  ============================================================================  */

#include "NewClassTest.h"

 

CNewClassTest::CNewClassTest() :  CActive(EPriorityStandard) // Standard priority

{

}

 

CNewClassTest* CNewClassTest::NewLC()

{  

    CNewClassTest* self = new ( ELeave ) CNewClassTest();  

    CleanupStack::PushL(self);  

    self->ConstructL();  return self;

}

 

CNewClassTest* CNewClassTest::NewL()

{  

    CNewClassTest* self = CNewClassTest::NewLC();  

    CleanupStack::Pop(); // self;  

    return self;

}

 

void CNewClassTest::ConstructL()

{  

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

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

}

 

CNewClassTest::~CNewClassTest()

{  

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

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

    // Delete instance variables if any

}

 

void CNewClassTest::DoCancel()

{  

    iTimer.Cancel();

}

 

void CNewClassTest::StartL(TInt aState, TTimeIntervalMicroSeconds32 aDelay)

{  

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

    iState = aState;  

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

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

}

 

void CNewClassTest::RunL()

{  

    if (iState == EUninitialized)  

    {   

        // older timer event, 当CActiveScheduler::Start()后,程序先到达这里   

        iState = 10;  

    }  

    else if(iState == EInitialized)  

    {   

        //// new timer event   

        iState = 201;   

        CActiveScheduler::Stop();  

    }

}

 

TInt CNewClassTest::RunError(TInt aError)

{  

    return aError;

}

 

// 测试代码

// TInt ThreadEntry(TAny *arg), 用户线程的入口函数,省略了一些必要的初始化

 

TInt ThreadEntry(TAny *arg)

{

     CNewClassTest *obj1 = CNewClassTest::NewL();      

    CNewClassTest *obj2 = CNewClassTest::NewL();     

    obj-1>StartL(CNewClassTest::EUninitialized,TTimeIntervalMicroSeconds32(1000000));  //1(s)     

    User::After(5000000);  // sleep 5(s)     

    obj2->StartL(CNewClassTest::EInitialized,TTimeIntervalMicroSeconds32(20000));  //20(ms)     

    CActiveScheduler::Start();     

    delete obj1;    

    delete obj2;

}

 

        以上代码演示了如何灵活使用CActiveScheduler::Start(),至于具体的实现上,还需要调整一下,CActiveScheduler::Start()的必须还要同时启动一个超时定时器,当在设定的超时时间内没有任何异步时间完成,则在超时AO内停止活动规划器CActiveScheduler::Stop(),这样等待下一个循环到来再启动活动规划器。此时可继续执行被CActiveScheduler::Start()方法挂起的语句和方法。

 

总结:

1. 可以解决移植代码中出现的上述情况

2. 异步事件的完成检测有时延

3. 因为是异步事件,对于一定的时延,还是可以接受的

原创粉丝点击