应该是主线程创建就可以了,异常可能是访问冲突,要在访问数据库的地方设置互斥:
先定义一个CRITICAL_SECTION结构的排斥区对象;
在进程使用之前,先对对象作初始化,调用下面函数:
VOID InitializeCriticalSection( LPCRITICAL_SECTION );
当一个线程使用排斥区时,调用函数
EnterCriticalSection或者TryEnterCriticalSection
要求占用,退出排斥区时 ,调用
LeaveCriticalSection
释放对排斥区对象的占用,供其它线程使用。
先定义一个CRITICAL_SECTION结构的排斥区对象;
在进程使用之前,先对对象作初始化,调用下面函数:
VOID InitializeCriticalSection( LPCRITICAL_SECTION );
当一个线程使用排斥区时,调用函数
EnterCriticalSection或者TryEnterCriticalSection
要求占用,退出排斥区时 ,调用
LeaveCriticalSection
释放对排斥区对象的占用,供其它线程使用。
这两天我就是这样做的,应当同步访问!
BOOL CLogThread::WriteLog(CString strProgramName, short nUnit, short nPort, short nChannel, short nType, CString strLog, short nInOrOut)
{
if (m_pLog == NULL)
{
if (!InitLog("127.0.0.1" , "c:\\logdb.mdb"))
{
AfxMessageBox("Cannot Initialize log dataase.");
return FALSE;
}
}
BSTR bstrCommandSource = strProgramName.AllocSysString () ;
BSTR bstrLog = strLog.AllocSysString() ;
CString strTime = (COleDateTime::GetCurrentTime ()).Format () ;
BSTR bstrTime = strTime.AllocSysString () ;
try
{
m_mutex.Lock (1000);
if ((m_pLog->WriteLog (bstrCommandSource ,
nUnit , nPort , nChannel , nType , bstrLog , bstrTime , nInOrOut)) == E_FAIL)
{
::SysFreeString (bstrCommandSource);
::SysFreeString (bstrLog);
::SysFreeString (bstrTime);
m_nLineNumber ++ ;
if (m_nLineNumber >= 5000)
{
m_pLog->ClearLog();
m_nLineNumber = 0 ;
}
return TRUE ;
}
else
{
::SysFreeString (bstrCommandSource);
::SysFreeString (bstrLog);
::SysFreeString(bstrTime);
return FALSE ;
}
m_mutex.Unlock ();
}
catch(_com_error &er)
{
TRACE(er.ErrorMessage ());
return FALSE ;
}
}
CLogThread就是这个处理ADO连接的内部线程,然后该线程创建DCOM连接以及创建ADO连接的操作如下:
BOOL CLogThread::InitLog(CString strIP, CString strLogDB)
{
CoInitialize(NULL);
COSERVERINFO pServInfo ;
pServInfo.dwReserved1 = 0 ;
CString servName = strIP;
_bstr_t bst ;
bst = servName ;
pServInfo.pwszName = bst ;
pServInfo.pAuthInfo = NULL ;
pServInfo.dwReserved2 = 0 ;
MULTI_QI qi = {&IID_IsvrLog , NULL , NOERROR} ; HRESULT hr ;
try
{
hr = CoCreateInstanceEx(CLSID_svrLog , NULL ,CLSCTX_REMOTE_SERVER , &pServInfo , 1, &qi);
// AfxMessageBox("Yes");
}
catch (_com_error &er)
{
AfxMessageBox(er.ErrorMessage() );
return FALSE ;
} if(FAILED(hr))
{
CString cs;
cs.Format("can't create com instance\n return code : %X",hr);
switch (hr)
{
case 0x80040154:
cs+="\n\nclass not registered (Proxy/Stub DLL not found?)";
break;
case 0x80070005:
cs+="\n\nAccess Denied";
break;
case 0x80080005:
cs+="\n\nServer execution failed";
break;
}
AfxMessageBox(cs);
return FALSE ;
}
m_pLog = (IsvrLog*)qi.pItf ;
try
{
BSTR str = strLogDB.AllocSysString () ;
m_pLog->OpenLogDB (str);
::SysFreeString (str);
}
catch(_com_error &er)
{
TRACE(er.ErrorMessage ()) ;
return FALSE ;
}
return TRUE ;
}
该线程由一个CLogFile类来创建,并且我只创建一次
void CLogfile::WriteLog(CString strLog, int type ,int nFlag)
{
if (m_pLogThread == NULL)
{
m_pLogThread = new CLogThread();
if (!m_pLogThread->CreateThread (0,0))
{
delete m_pLogThread ;
return ;
}
}
if (m_pLogThread->WriteLog ("Muxdll" , -1,-1,-1,type , strLog , nFlag))
{ }
}
在系统的主线程与其他子线程中用一个全局的变量 CLogfile g_fpLog,来引用该对象,
extern CLogfile g_fpLog;
g_fpLog.WriteLog(CString strLog, int type ,int nFlag)
我在主线程中可以将数据写入数据库,但子线程无法调用数据库的写入函数。
但是如果我在CLogThread的WriteLog函数中,每一次都连接一次DCOM,并且打开数据库连接,则我可以成功地写入数据,但是太占资源和内存了。