开发环境:VC2005, ADO(msado.dll版本1132 or 1128),线程数量在10~30之间
关键点 : 基于对话框的mfc程序,app的initinstance中调用了AfxOleInit(); 所有的ADO数据库访问被封装在一个dll中;每次查询使用一个新连接,每个查询结果采用临时变量,并立即取出数据后关闭;
问题:
1. 每次当两个线程同时进行ado操作时必发异常, 比如线程A在 conn->Execute,线程B在RecordSet.CreateInstance; 线程A的Recordset在GetCollect,线程B的RecordSet在CreateInstance时都会异常;
异常发生的函数基本上在Conn->Execute和RecordSet.CreateInstance这两个函数中;
后来我对 RecordSet的生成和Conn的查询进行加锁,如下:
Lock();
AdoRecordSet rs;
conn = DBConnPool.GetConnection();
conn->Execute(strSQL, rs);
Unlock();
...
use rs;
rs.Close(); 结果use rs;也会和conn的查询以及rs的createinstance冲突导致异常;
最后,整个加到锁里面, 如下
Lock();
AdoRecordSet rs;
conn = DBConnPool.GetConnection();
conn->Execute(strSQL, rs);
...
use rs;
rs.Close();
Unlock();
貌似问题可以得到解决;(长时间的运行之后未见异常); 实在是不能理解,明明是不同的连接和结果集,为什么还要同步呢? 2. 在网上查资料,有些人说需要在每个线程的线程函数中调用coinitialize和couninitialize,结果我发现在有的机器上,线程函数的第一句调用coinitialize会返回s_ok,而有的机器上却返回s_false,明明是同样的代码,怎么会有这种区别呢?
请各位不吝赐教,不胜感激.
关键点 : 基于对话框的mfc程序,app的initinstance中调用了AfxOleInit(); 所有的ADO数据库访问被封装在一个dll中;每次查询使用一个新连接,每个查询结果采用临时变量,并立即取出数据后关闭;
问题:
1. 每次当两个线程同时进行ado操作时必发异常, 比如线程A在 conn->Execute,线程B在RecordSet.CreateInstance; 线程A的Recordset在GetCollect,线程B的RecordSet在CreateInstance时都会异常;
异常发生的函数基本上在Conn->Execute和RecordSet.CreateInstance这两个函数中;
后来我对 RecordSet的生成和Conn的查询进行加锁,如下:
Lock();
AdoRecordSet rs;
conn = DBConnPool.GetConnection();
conn->Execute(strSQL, rs);
Unlock();
...
use rs;
rs.Close(); 结果use rs;也会和conn的查询以及rs的createinstance冲突导致异常;
最后,整个加到锁里面, 如下
Lock();
AdoRecordSet rs;
conn = DBConnPool.GetConnection();
conn->Execute(strSQL, rs);
...
use rs;
rs.Close();
Unlock();
貌似问题可以得到解决;(长时间的运行之后未见异常); 实在是不能理解,明明是不同的连接和结果集,为什么还要同步呢? 2. 在网上查资料,有些人说需要在每个线程的线程函数中调用coinitialize和couninitialize,结果我发现在有的机器上,线程函数的第一句调用coinitialize会返回s_ok,而有的机器上却返回s_false,明明是同样的代码,怎么会有这种区别呢?
请各位不吝赐教,不胜感激.
解决方案 »
- 【求助】VC++6.0用GDI+想做出边框透明渐变效果的对话框,怎么办?
- CEdit 问题:如何 总是在 CEdit最后一行添加内容
- 提取LISTBOX里面的一个字符串,并提取出里面的指定数字
- 请问IE的收藏夹有没有事件触发?或者说有什么连接点可以知道??DISPID_ADDFAVORITE吗?
- 已经实现了给基于对话框的程序加启动画面。可是当启动画面显示时,主窗口就已经出来了,这有点影响美观。请问如何让启动画面消失后再出现
- 请高手指点:如何在两个不同的程序之间传递信息?
- 如何在Static Text 中显示一Double 类型的数值呢!
- VS.NET CHS 7CD,要的话自己去下吧,甭给俺发EMAIL了,HOHO~
- 请教:如何在vc程序中查询dns服务器的mx项?
- 怎样复位一个人工重设(ManualReset)等待定时器
- VS2005中如何制作MFC activeX控件
- 共享数据段问题
UINT MyProc(LPVOID param)
{
HRESULT hr = ::CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
if(FAILED(hr))
{
AfxMessageBox("初始化 COM 失败!");
return 1;
}
//...
::CoUninitialize();
return 0;}
我发现我把很多RecordSet传递到Ado之外的业务类进行访问,这下要同步的话困难了~如果这样也要同步的话,估计效率会有很大的损失,因为有些recordset返回的记录很多
连接的建立是在线程外,在程序初始化的时候建立了50个左右的连接
以后一直使用这50个连接查询频繁倒是真的,手工操作的话一般不出异常,但是用自动化测试工具(QTP),一般1个小时内会出异常
CreateInstance里面QueryInterface(__uuid(RecordSet), NULL, __uuid(IUnknown), (void*)(pIunknown))函数
该函数返回s_ok,可pIUnknown却为未初始化的值0xcccccccc,导致后面的执行异常
另一个是
Conn->Execute里面的raw_Execute()函数的参数bstr_t的函数operator wchar_t*()异常,追踪发现Execute里面传进去的sql语句是好的,但一到raw_Execute里面的bstr_t,居然是个0x00000000,导致后面的操作失败上面的两个函数都是vc自己内部的函数,我也是在调试中发现的,真是一点办法也没有了
CreateInstance(__uuid(RecordSet), NULL, __uuid(IUnknown), (void**)&pUnk)_bstr_t变量是怎么构造的?
}
catch(...){
}
捕捉异常吧,弄一个变量看看出现异常的次数是否多到无法忍受
{
}
catch貌似捕捉不到,程序直接崩溃~~"IUnknown* pUnk = NULL;
CreateInstance(__uuid(RecordSet), NULL, __uuid(IUnknown), (void**)&pUnk)
_bstr_t变量是怎么构造的?"
哪个CreateInstance是vc的内部代码,我打字的时候少写了一个*号;
_bstr_t的构造很简单,就是_bstr_t(_T("select *...")),所有的操作都放在一个队列中?
有的后续操作要依赖数据库的数据改变的,有的操作要立即返回,貌似有难度~
问题在于,异常是偶发的,同一段代码运行很多次都不异常,直到某个偶然时机才出现异常