——MFC多线程下AfxOleInit()的使用
1、问题描述:
因为要在MFC程序中使用ADO连接ORACLE数据库,所以根据查找的资料在CXXXApp::InitInstance()中调用了AfxOleInit(),但是不想,程序在Debug模式刚开始启动的时候就报错debug assertionfailed,调试得出错的断言为oleinit.cpp中的代码:
BOOL AFXAPI AfxOleInit()
{
_AFX_THREAD_STATE*pState = AfxGetThreadState();
ASSERT(!pState->m_bNeedTerm); // calling it twice?
}
2、问题分析:
(1)该函数可能被执行了两次,但是搜索整个工程并没有发现啊,于是查看调用堆栈(在主进程中的ADO连接我都是设置成了随用随连,所以只在每一个用到数据库连接的地方先执行AdoConn类的Init方法,执行完成后再关闭连接。因此我在Init方法中添加了AfxOleInit()方法;
(2)但是在调用堆栈中发现在调用Init方法的时候,执行AfxOleInit()之后,就跳到了上面的出错断言语句处,说明我定义的就是第二次调用了;
(3)问题就出在这里,对于主进程,在InitInstance()方法中已经执行了一次AfxOleInit(),而在初始化连接Init方法中再次进行了调用,导致了两次的调用;
(4)于是我尝试把这一行注释掉,调试运行,发现虽然在主进程中可以成功连接数据库了,但是我的子线程中的数据库初始化失败了。说明子线程中是第一次调用Init方法中的AfxOleInit();
3、问题解决:
(1)通过查找资料以及API中查找发现:AfxOleInit()方法一般会在软件初始化的时候App::InitInstance()添加,但是多线程里面用到OLE就失效,是因为AfxOleInit只支持单线程,每个子线程中需要再次初始化一遍,当然也可用 CoInitialize代替,不过需要CoUninitialize。
(2)由于需要实现多线程中对数据库的操作,因此子线程中也需要实现AfxOleInit()初始化,但是我把CXXXApp::InitInstance()中的AfxOleInit()删掉,主进程中同样会出现调用两次的断言,目前尚未找到原因(先MARK一下),所以我只能把我的ADOConn类中Init函数中的AfxOleInit()添加判断,如果是子线程调用则执行,否则在主进程中调用Init就不执行。
最后调试运行,不再提示该问题,解决!
PS
CXXXApp::InitInstance()中的初始化最终修改成了如下形式:
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}