前些日子转化图片又用到了异步操作转同步操作,用 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 的设置不对。