在回调函数中有时需要删除调用该函数的类,比如网络回调函数中如果下载完成有时需要删掉该网络类,此时如果在该函数中删除了调用该函数的类,回调函数后面如果再使用该类的变量就会错误退出(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();//就 相当于Active的SetActive()了
}
}
因为这个AsyncCallBack是继承于CAsyncOneShot的,所以他的call里面实际有自激活的过程iThread.RequestComplete(pS,0); KErrNone = 0,即给当前线程信号量并且激活active。这样的话在ccoeenv的runl运行完,就可以进AsyncCallBack的runL了。
4、回调
RunL()
{
调用TCallBack的handler function.
}
5、回调函数定义
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了么。