XPCOM C++;多线程和javascript回调 背景
在XULRunner版本Belowe12.0中,它可以工作,但当我尝试将它移植到12.0或更高版本时,它会使应用程序崩溃。 主要原因是,在sdk v12或更新版本中,开发人员将代理对象删除到xpcom组件,并建议替换它 通过使用nsRunnable/nsIRunnable包装对象,并通过函数NS\u DispatchToMainThread将调用路由到主线程(单击)XPCOM C++;多线程和javascript回调 背景,javascript,c++,multithreading,xul,xpcom,Javascript,C++,Multithreading,Xul,Xpcom,在XULRunner版本Belowe12.0中,它可以工作,但当我尝试将它移植到12.0或更高版本时,它会使应用程序崩溃。 主要原因是,在sdk v12或更新版本中,开发人员将代理对象删除到xpcom组件,并建议替换它 通过使用nsRunnable/nsIRunnable包装对象,并通过函数NS\u DispatchToMainThread将调用路由到主线程(单击) nsDBService::Query //main thread ok NS_DispatchToMainThread //mai
nsDBService::Query //main thread ok
NS_DispatchToMainThread //main thread
nsResultCallback::Run //main thread
nsIDBCallback::OnInfo //main thread ok
我在开发什么?
我创建了db连接器,它是异步的,通过回调与主线程通信。
使用:xulrunnerv6,移植到xulrunnerv17或更高版本
nsDBService::Query //main thread ok
NS_DispatchToMainThread //main thread
nsResultCallback::Run //main thread
nsIDBCallback::OnInfo //main thread ok
//nsIDBCallback.idl
[可编写脚本、函数、uuid(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)]
接口nsIDBCallback:nsidbSupports{
void onInfo(在长阶段、长状态、字符串信息中);
}
//h,它是XPCOM组件
nsDBService类:公共NSIBSERVICE,nsIRunnable
{
公众:
NS_DECL_ISUPPORTS
不可执行
NS_DECL_NSIDBSERVICE
私人:
向量线程;
std::向量回调;
std::向量sqls;
nsIThread*makenethread();
无效运行IfNotBussy();
公众:
NS_IMETHODIMP查询(const char*sql,nsIDBCallback*callback);
}
//nsDBService.cpp
//将查询和其他数据添加到缓冲区,
//它是线程安全的,有使用互斥的
NS_IMETHODIMP nsDBService::Query(const char*sql,nsIDBCallback*callback)
{
回调。推回(回调);
sqls.push_-back(sql);
threads.push_back(makeNewThread());
//如果db驱动程序空闲,则运行添加的操作,
//若驱动程序是bussy,那个么调用就在缓冲区中,需要等待
runOperationIfNotBussy();
返回NS_OK;
}
void nsDBService::runOperationIfNotBussy()
{
//一些条件、测试等。
//在列表上运行第一个操作
//运行线程,仍然可以吗
if(…)threads.front()->Dispatch(这是nsIEventTarget::Dispatch_NORMAL);
}
//如果此方法被另一个线程+db查询使用,
//然后其他操作无法运行,需要等待
//像fifo一样存储和支持操作
NS_IMETHODIMP nsDBService::运行(无效)
{
//其他一些行动
//后台的真实数据库操作
int32\u t相位=3;//结束相位
int32\u t code=0;//确定
const char*msg=“确定”;
nsIDBCallback*callback=callbacks.pop();
//使用可运行接口包装回调函数
nsIRunnable*runCallback=新的nsResultCallback(回调,
阶段,
代码,
味精);
//将事件路由到主线程
NS_DispatchToMainThread(runCallback,NS_DISPATCH_NORMAL);
runOperationIfNotBussy();
}
//nsResultCallback.h
类nsResultCallback:public nsRunnable
{
公众:
NS_DECL_ISUPPORTS
公众:
不可执行
私人:
nsIDBCallback*回调;
int32_t再相位;
int32_t resStatus;
const char*resMessage;
公众:
nsResultCallback(nsIDBCallback*回调,
int32_t阶段,
国际地位,
const std::字符串和消息)
:回调(回调),
再相位(相位),
雷斯塔图斯(地位),
resMessage(c_str_clone(message.c_str()){};
~nsResultCallback();
};
//nsResultCallback.cpp
NS_i方法DIMP nsResultCallback::运行(无效)
{
nsresult rv=NS\u错误\u故障;
尝试
{
//应用程序的手和粉碎!
if(this->callback)this->callback->OnInfo(resPhase、resStatus、resMessage);
}
捕获(…)
{
rv=NS\u错误\u意外;
ERRF(“nsbackack::从回调运行调用方法OnInfo失败”);
}
返回rv;
}
调用
//*.js
nsDBService.query(“从t中选择*”,函数(阶段、代码、mes){
//某些UI操作或其他db查询
});
问题:
当代码执行如下所示时,应用程序冻结和崩溃:
nsDBService::Query //main thread ok
NS_DispatchToMainThread //main thread
nsResultCallback::Run //main thread
nsIDBCallback::OnInfo //main thread ok
如果代码执行如下所示,则一切正常:
nsDBService::Query //main thread ok
NS_DispatchToMainThread //main thread
nsResultCallback::Run //main thread
nsIDBCallback::OnInfo //main thread ok
nsDBService::Query //main thread ok
NS_DispatchToMainThread //main thread
nsResultCallback::Run //main thread
nsIDBCallback::OnInfo //main thread ok
问题:
当从NS_DispatchToMainThread调用nsIDBCallback,从其他线程调用NS_DispatchToMainThread,然后从主应用程序线程调用NS_DispatchToMainThread时,执行失败,我缺少什么,不明白?或者背景任务的另一种方法是什么?无法重现,因为您没有提供一个完整的示例,所以请给出以下注释:
nsDBService::Query //main thread ok
NS_DispatchToMainThread //main thread
nsResultCallback::Run //main thread
nsIDBCallback::OnInfo //main thread ok
我注意到的第一件事是std::vector
的跨线程访问。您在注释中写了一些关于互斥体的内容,所以这可能没问题
nsDBService::Query //main thread ok
NS_DispatchToMainThread //main thread
nsResultCallback::Run //main thread
nsIDBCallback::OnInfo //main thread ok
肯定是错了,存储了指向nsIDBCallback
的原始指针。XPCOM对象是ref计数的。因此,只要Query
方法返回,如果没有其他引用,那么底层对象可能是delete
d,在向量中留下一个悬空指针。我想这就是这里发生的事情!
在线程处理完对象之前,您需要保持对象的活动状态,最好是将其放在某个地方,例如,在
nsDBService::Query //main thread ok
NS_DispatchToMainThread //main thread
nsResultCallback::Run //main thread
nsIDBCallback::OnInfo //main thread ok
PS:原来这是一个有点老的问题,我错过了。。。很抱歉延迟回复:p
nsDBService::Query //main thread ok
NS_DispatchToMainThread //main thread
nsResultCallback::Run //main thread
nsIDBCallback::OnInfo //main thread ok