异步操作转同步

来源:互联网 发布:华为手机短信恢复软件 编辑:程序博客网 时间:2024/06/01 09:48

前些日子转化图片又用到了异步操作转同步操作,用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();
这行函数应该在iImageEncoderRunL中调用,它会通知iWait停止等待。
这样就成功了。
在第三版中如果iWait->Start();//Panics with KERN-EXEC 3
多半是mmp文件中EPOCSTACKSIZE 的设置不对。