我写了一个 DLL ,是专门读写数据库的,代码如下:extern "C"  __declspec(dllexport) bool  Init()
{
Log("开始初始化数据库接口..");
if (strcmp(strConn, "") == 0)
return false;
try
{
if (IsOpen)
pConn->Close();
Log(strConn);
IsOpen = (pConn->Open(_bstr_t(LPCTSTR(strConn)), "", "", adConnectUnspecified) == S_OK);
Log("OK");
return IsOpen;
}
catch(_com_error e)
{
Log(strcat("连接数据库发生异常!\n\nErrorMessage: ", e.ErrorMessage()));
return false;
}
catch(...)
{
Log("连接数据库时发生未知错误!");
}
return false;
}extern "C"  __declspec(dllexport) bool Submit(CMPP_SUBMIT &msg)
{
bool done = false;
try
{
string SendTime = GetCurNow();
sprintf( strSQL, "select * from SMS_Submit order by ID"); if (pRs->Open(_variant_t(strSQL), _variant_t((IDispatch*)pConn), adOpenStatic, adLockOptimistic, adCmdText) != S_OK)
return false;

if(!pRs->adoEOF)
{                           //代码略..
pRs->Update();
pRs->MoveNext();
done = true;
}
pRs->Close();
}
catch(_com_error e)
{
pRs->Close();
char ErrChr[500];
sprintf(ErrChr, "取数据失败,[%s]", e.ErrorMessage());
Log(ErrChr);
done = false;
} return done;
}//发送数据返回
extern "C"  __declspec(dllexport) bool Submit_Resp(int SeqID, int Msg_ID, int Result)
{
bool done; char cSql[100], temChr[200];
sprintf(cSql, "select * from SMS_SubmitResp where ID<0");
Log(cSql); sprintf(temChr, "收到一条消息返回 SeqID:%d Msg_ID:%d Result:%d", SeqID, Msg_ID, Result);
Log(temChr); try
{
if (pRs1->Open(_variant_t(cSql), _variant_t((IDispatch*)pConn), adOpenStatic, adLockOptimistic, adCmdText) != S_OK)
return false;

string tTime = GetCurNow();
pRs1->AddNew();
pRs1->PutCollect(_variant_t("SeqID"),_variant_t((long)SeqID));
pRs1->PutCollect(_variant_t("MsgID"),_variant_t((long)Msg_ID));
pRs1->PutCollect(_variant_t("Result"),_variant_t((long)Result));
pRs1->PutCollect(_variant_t("ResultTime"),_variant_t(tTime.c_str()));
pRs1->Update();
pRs1->Close();
Log("已经保存了。");
done = true;
}
catch(_com_error e)
{
pRs1->Close();
char ErrChr[500];
sprintf(ErrChr, "保存发送返回出错了,SQL:%s, Err:[%s]", cSql, e.ErrorMessage());
Log(ErrChr);
done = false;
}
return done;
}
另外一个程序中有两个线程,一个线程调用 Submit ,另一个线程调用 Submit_Resp,如果线程一正在读数据,线程二也修改数据库,程序就会马上出错。但平时很少时(就是两个线程不同时修改数据库)就不会出错,运行很正常。
不是是什么问题?

解决方案 »

  1.   

    数据库在多线程或多用户操作的时候,必须有一个互斥机制
    你的submit有update操作,则一定会有一个锁的操作,所以两个线程在对临界区操作时候,一定出现异常,你可以采用事务
    当前的所有操作交给事务对象来处理,由该Transaction一次commit
      

  2.   

    用CMutex保证同时访问一个ado对象。这些代码重入问题都是由于多线程所产生,解决办法有两个。一个是如我前面所说。另一个办法是每个调用数据库的线程都有自己的conn对象。就是说每个线程都单独建立一个conn连接
      

  3.   

    如果我在程序初始化时加载 DLL,然后在线程一中调用 DLL中的Submit, 线程二中调用DLL中的Submit_Resp,这样是不是有冲突的?我看了你们的方法后,我给程序加上了:
    EnterCriticalSection( &cmpp._csec_ado);
    Operation_Submit_Resp(seqid, msgid, result);
    LeaveCriticalSection( &cmpp._csec_ado);
    但是还是有时会出错,就是比以前少了些,我怀疑是不是DLL也有这种情况?