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