回调函数中删除调用者

时间:2022-11-26 20:13:56

在回调函数中有时需要删除调用该函数的类,比如网络回调函数中如果下载完成有时需要删掉该网络类,此时如果在该函数中删除了调用该函数的类,回调函数后面如果再使用该类的变量就会错误退出(kern-exec3),那么如何在回调函数中删除调用者呢?

 

CAsyncCallBack类可以解决解决这类问题。

 

实现的原理是这样的:由CAsyncCallBack来执行调用回调的操作,而在原来调用回调的地方执行CAsyncCallBack::CallBack()。

CAsyncCallBack是个Cactive,也就是说,调用者类在调用了CAsyncCallBack::CallBack(),会继续往下执行,完成后才会执行到CAsyncCallBack,这样删除调用者就没什么问题了。

 

CAsyncCallBack的用法:

 

因为在Gui的事件处理函数 比如像handleWsEventL或者offereyEvent或者handleCommand这些函数都是运行在CCoeEnv这个活动对象RunL里面的,为了不阻塞该Runl所以才要把一些需要等待的操作用AsyncCallBack的方式移出到别的RunL中执行

一般作为成员变量使用,以下是具体说明

1、定义:

 Class A

{

private: 

CAsyncCallBack* iCall;

}

2、初始化:

A::PreLayoutDynInitL()

{

     iCall = new (ELeave) CAsyncCallBack
TCallBack( LaunchDlgCallback, this ),
CActive::EPriorityStandard );

}

因为CAsyncCallBack是派生于CAtive的,这句话就是相当于Active的构造,只不过要传递一个TCallBack对象

TCallBack构造函数:inline TCallBack(TInt (*aFunction)(TAny* aPtr),TAny* aPtr);

TInt (*aFunction)(TAny* aPtr):函数地址,TAny* aPtr:对象地址

3、激活:

A::HandleCommandL()

{

if (!iCall->IsActive())

{

iCall->Call();//就 相当于ActiveSetActive()了

}

因为这个AsyncCallBack是继承于CAsyncOneShot的,所以他的call里面实际有自激活的过程iThread.RequestComplete(pS,0); KErrNone = 0,即给当前线程信号量并且激活active。这样的话在ccoeenvrunl运行完,就可以进AsyncCallBackrunL了。

4、回调

RunL()

{

调用TCallBackhandler function.

}

5、回调函数定义

注意:1、回调用static的函数获得全局地址
      2、在使用  TAny* aDlg前要做 类型转换。

TInt A::LaunchDlgCallback( TAny* aDlg )
{
A* dlg = 
static_cast<CWVSettingsUIServerListDialog*>( aDlg );  
TRAP_IGNORE( dlg->DoLaunchCorrectDialogL() );

    return EFalse;
}

    在这里说一下为什么要用static的函数,因为callback使用系统,那么如果用类成员函数的话,会隐藏this指针在里面,调用还得 this->B()这样的话系统怎么知道this,所以要用static全局地址。这样不会通过this,而且用static还能保证干净的全局地 址空间,作用域就是当前编译单元。然后callback你没有this指针的话又不行,因为你 最终还要用成员函数,所以TCallBack要求你在用一个this指针作为参数传递过去,这样系统既知道你的函数地址还知道你的对象地址,其实他是把你转过来的对象地址扔到你的callback函数里,这样你回 调函数里一地址转换不久可以的到this了么。