异步操作转同步

    技术2022-05-19  21

    前些日子转化图片又用到了异步操作转同步操作,用 User::WaitForRequest() 函数阻塞等待实现同步,但当频繁操作时会出现异常(转化4张图片内没有问题,当大批量的时候就会报错)故通过CActiveSchedulerWait类实现同步,一下为实验代码:

     

    /*  ============================================================================  Name        : LoadimgEngine.h  Author      : Robin.Mu  Version     : 1.0  Copyright   : Your copyright notice  Description : CLoadimgEngine declaration  ============================================================================  */ #ifndef LOADIMGENGINE_H #define LOADIMGENGINE_H #include <e32base.h>    // For CActive, link against: euser.lib #include <e32std.h>        // For RTimer, link against: euser.lib class CActiveSchedulerWait; class CLoadimgEngine : public CActive     { public:     // Cancel and destroy     ~CLoadimgEngine();     // Two-phased constructor.     static CLoadimgEngine* NewL();     // Two-phased constructor.     static CLoadimgEngine* NewLC(); public:     // New functions     // Function for making the initial request     void StartL(TInt64 aDelay); private:     // C++ constructor     CLoadimgEngine();     // 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); private:     enum TLoadimgEngineState         {         EUninitialized, // Uninitialized         EInitialized, // Initalized         EError         // Error condition         }; private:     TInt iState; // State of the active object //    RTimer iTimer; // Provides async timing service     CImageDecoder* decoder;     CFbsBitmap* iFrame;     CActiveSchedulerWait *iWait;     };

     

     

    /*  ============================================================================  Name        : LoadimgEngine.cpp  Author      : Robin.Mu  Version     : 1.0  Copyright   : Your copyright notice  Description : CLoadimgEngine implementation  ============================================================================  */ #include <f32file.h> #include <imageconversion.h> #include "LoadimgEngine.h" #include <coemain.h> CLoadimgEngine::CLoadimgEngine() :     CActive(EPriorityStandard) // Standard priority     {     } CLoadimgEngine* CLoadimgEngine::NewLC()     {     CLoadimgEngine* self = new (ELeave) CLoadimgEngine();     CleanupStack::PushL(self);     self->ConstructL();     return self;     } CLoadimgEngine* CLoadimgEngine::NewL()     {     CLoadimgEngine* self = CLoadimgEngine::NewLC();     CleanupStack::Pop(); // self;     return self;     } void CLoadimgEngine::ConstructL()     { //    User::LeaveIfError(iTimer.CreateLocal()); // Initialize timer     CActiveScheduler::Add(this); // Add to scheduler        } CLoadimgEngine::~CLoadimgEngine()     {     Cancel(); // Cancel any request, if outstanding //    iTimer.Close(); // Destroy the RTimer object     delete iFrame;     delete decoder;     // Delete instance variables if any     delete iWait;     } void CLoadimgEngine::DoCancel()     { //    iTimer.Cancel();     if(decoder)         {         decoder->Cancel();         }        } void CLoadimgEngine::StartL(TInt64 aDelay)     {     Cancel(); // Cancel any request, just to be sure     iState = EUninitialized; //    iTimer.After(iStatus, aDelay); // Set for later     iWait = new(ELeave)CActiveSchedulerWait;     RFs& fs = CCoeEnv::Static()->FsSession();     decoder = CImageDecoder::FileNewL(fs,_L("c://Data//Images//SMILEY.bmp "),CImageDecoder::EOptionAlwaysThread );     TInt iPlayImageMaxNum = decoder->FrameCount(); // image count         iFrame = new(ELeave)CFbsBitmap;        iFrame->Create(decoder->FrameInfo().iOverallSizeInPixels,decoder->FrameInfo().iFrameDisplayMode);         decoder->Convert(&iStatus, *iFrame);        SetActive(); // Tell scheduler a request is active     iWait->Start();     } void CLoadimgEngine::RunL()     {     if (iState == EUninitialized)         {         // Do something the first time RunL() is called         iState = EInitialized;         }     else if (iState != EError)         {         // Do something         }         iWait->AsyncStop();     //    iTimer.After(iStatus, 1000000); // Set for 1 sec later //    SetActive(); // Tell scheduler a request is active     } TInt CLoadimgEngine::RunError(TInt aError)     {     return aError;     }

    实现思路:

     

    CActiveSchedulerWait CActiveScheduler 是合作使用的,所以你必须已经安装 CActiveScheduler 并开启,这在 GUI 程序中并不困难,因为一般架构默 认生成,在 exe 中就需要好好安装一个活动调度器。 首先初始化一个 CActiveSchedulerWait ,然后在你的异步对象函数后调用,例如 iImageEncoder->Convert( &iStatus, *iBitmap ); SetActive(); iWait->Start(); 这样程序就会卡在这里等待异步事件完成。 但是当异步事件完成后,你必须通知 aWait->AsyncStop(); 这行函数应该在 iImageEncoder RunL 中调用,它会通知 iWait 停止等待。 这样就成功了。 在第三版中如果 iWait->Start();//Panics with KERN-EXEC 3 多半是 mmp 文件中 EPOCSTACKSIZE 的设置不对。


    最新回复(0)