在MFC中利用ADO访问SQL Server 2008如何使用多线程,插入读取数据

时间:2023-01-03 17:31:49
我的操作过程如下:

新建一个基于对话框的MFC程序Test
在StdAfx.h中 #include<afxdb.h>  
在StdAfx.h中 #import "C:\Program Files (x86)\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF") rename("BOF","adoBOF")
在CTestDlg类的OnInitDialog()中
第一,初始化COM库
AfxOleInit();

第二,定义两个全局的智能指针  

_ConnectionPtr m_pConnection; 
_CommandPtr m_pCommand;

下来用m_pConnection连接我的数据库 

CString strSQL;
HRESULT hr;
try
{
hr=m_pConnection.CreateInstance(__uuidof(Connection));
//m_pConnection->CursorLocation=adUseClient;
strSQL="Provider=SQLOLEDB;Server=1104A01\\MSSQLSERVER1104;Database=DCS;UID=sa;PWD=726";
if(SUCCEEDED(hr))

hr=m_pConnection->Open(_bstr_t(strSQL),"","",adModeUnknown);

}

catch(_com_error e) //捕捉异常     
{
CString errormessage;
errormessage.Format(_T("连接数据库失败!\r\n错误信息:%s",e.ErrorMessage()));
AfxMessageBox(errormessage);//显示错误信息

return FALSE;     
}

接下来在按钮BUTTON的点击响应函数中开启五个线程,然后在每个线程中向数据库插入数据

void CThreadJJDlg::OnBnClickedBtnThread5()
{
// TODO: 在此添加控件通知处理程序代码
AfxBeginThread(Thread1,THREAD_PRIORITY_NORMAL,0,0,NULL);
AfxBeginThread(Thread2,THREAD_PRIORITY_NORMAL,0,0,NULL);
AfxBeginThread(Thread3,THREAD_PRIORITY_NORMAL,0,0,NULL);
AfxBeginThread(Thread4,THREAD_PRIORITY_NORMAL,0,0,NULL);
AfxBeginThread(Thread5,THREAD_PRIORITY_NORMAL,0,0,NULL);
}

下面是每个线程的执行过程,在每个线程中,用m_pCommand调用数据库中的一个名为Insert_date_data的存储过程将数据存入表格

UINT Thread1(LPVOID lpParam)
{
    CString str;
    clock_t t_Start , t_End;
//这两个用于计算程序运行的时间,数据插入时间
try
{
    m_pCommand.CreateInstance(__uuidof(Command));
    m_pCommand->ActiveConnection = m_pConnection;
    m_pCommand->CommandText="Insert_date_data";// 制定调用哪个存储过程
    m_pCommand->CommandType=adCmdStoredProc;     // 制定Sql命令类型是存储过程
    m_pCommand->Parameters->Refresh();

    m_pCommand->Parameters->GetItem((long)1)->Value ="2013-03-13 21:34:50";//按存储过程的参数顺序给参数赋值
    m_pCommand->Parameters->GetItem((long)2)->Value =100;

    m_pCommand->Parameters->GetItem((long)3)->Value ="1234567890123456789012345678901234567890";
}

catch(_com_error e) //捕捉异常     
{
    CString errormessage;
    errormessage.Format(_T("连接数据库失败!\r\n错误信息:%s",e.ErrorMessage()));
    AfxMessageBox(errormessage);//显示错误信息

    return FALSE;     
}
t_Start = clock();
m_pConnection->BeginTrans();//开启一个事务
while(num--)
{
m_pCommand->Execute(0,0,adCmdStoredProc);
}
    m_pConnection->CommitTrans();//执行事务
    t_End = clock();
    str.Format("线程1所用时间为:%d",(t_End - t_Start));
    ::SetDlgItemText(AfxGetMainWnd()->m_hWnd,IDC_EDIT1,str);

return 0;
}

其余的四个线程和这个是一模一样的,当只开一个线程的时候,程序运行没有问题,为什么当两个线程以上时程序就会报错
在MFC中利用ADO访问SQL Server 2008如何使用多线程,插入读取数据


求各位大神指导一下小弟,谢谢谢谢谢谢

8 个解决方案

#1


当前的这种数据插入方式,按每条记录30字节算,插入25000条数据大约用时1.2秒左右,有没有更好的优化办法?

#2


多个线程共用一个Connection,这种情况是要加锁同步或者开事务的,会影响效率
试试改为一个线程一个Connection

#3


另外,每个线程回调函数开头都调用一下AfxOleInit();

#4


引用 3 楼 stjay 的回复:
另外,每个线程回调函数开头都调用一下AfxOleInit();


UINT Thread1(LPVOID lpParam)
{
CString str;
clock_t t_Start , t_End;


//初始化COM库
AfxOleInit();
//连接数据库
//建立数据库的连接需要使用Connection Object。步骤如下:
//定义一个_ConnectionPtr类型的指针,代码如下: 
//_ConnectionPtr m_pConnection;  
//调用CreateInstance方法实例化: 
//m_pConnection.CreateInstance(__uuidof(Connection));

CString strSQL;
HRESULT hr;
_ConnectionPtr m_pConnection; 
try
{
hr=m_pConnection.CreateInstance(__uuidof(Connection));
m_pConnection->CursorLocation=adUseClient;
strSQL="Provider=SQLOLEDB;Server=1104A01\\MSSQLSERVER1104;Database=DCS;UID=sa;PWD=726";
if(SUCCEEDED(hr))

hr=m_pConnection->Open(_bstr_t(strSQL),"","",adModeUnknown);

}

catch(_com_error e) //捕捉异常     
{
CString errormessage;
errormessage.Format(_T("连接数据库1失败!\r\n错误信息:%s",e.ErrorMessage()));
AfxMessageBox(errormessage);//显示错误信息

return FALSE;     
}
_CommandPtr m_pCommand;
try
{

m_pCommand.CreateInstance(__uuidof(Command));
m_pCommand->ActiveConnection = m_pConnection;
m_pCommand->CommandText="Insert_date_data";// 制定调用哪个存储过程
m_pCommand->CommandType=adCmdStoredProc;     // 制定Sql命令类型是存储过程
m_pCommand->Parameters->Refresh();

m_pCommand->Parameters->GetItem((long)1)->Value ="2013-03-13 21:34:50";//按存储过程的参数顺序给参数赋值
m_pCommand->Parameters->GetItem((long)2)->Value =100;
m_pCommand->Parameters->GetItem((long)3)->Value ="1234567890123456789012345678901234567890123456789012345678901234567890";
}

catch(_com_error e) //捕捉异常     
{
CString errormessage;
errormessage.Format(_T("连接数据库1失败!\r\n错误信息:%s",e.ErrorMessage()));
AfxMessageBox(errormessage);//显示错误信息

return FALSE;     
}
t_Start = clock();
m_pConnection->BeginTrans();
while(num--)
{
m_pCommand->Execute(0,0,adCmdStoredProc);
}
m_pConnection->CommitTrans();
t_End = clock();
str.Format("线程1所用时间为:%d",(t_End - t_Start));
::SetDlgItemText(AfxGetMainWnd()->m_hWnd,IDC_EDIT1,str);
Sleep(2000);
return 0;

在线程2中我定义了
_ConnectionPtr   m_pConnection2
_CommandPtr m_pCommand2
我用两个编辑框显示每个线程运行的时间,
但是每次只有一个线程能够运行结束,并显示运行时间,另一个线程一进运行数据一直没有写进数据库,这是为什么?有时候线程1正常,有时候线程2正常,求助啊...

#5


已经解决了,谢谢楼上的

#6


引用 3 楼 stjay 的回复:
另外,每个线程回调函数开头都调用一下AfxOleInit();

我两在两个线程向数据库写数据,为什么有些数据写不进数据库?会丢失一些数据?速度慢的时候,不会出现这种情况,一量MFC写的太快,数据库就丢数据,如何解决

#7


引用 6 楼 cekong126 的回复:
Quote: 引用 3 楼 stjay 的回复:

另外,每个线程回调函数开头都调用一下AfxOleInit();

我两在两个线程向数据库写数据,为什么有些数据写不进数据库?会丢失一些数据?速度慢的时候,不会出现这种情况,一量MFC写的太快,数据库就丢数据,如何解决


求解 问题该如何解决

#8


线程不同步的缘故 

#1


当前的这种数据插入方式,按每条记录30字节算,插入25000条数据大约用时1.2秒左右,有没有更好的优化办法?

#2


多个线程共用一个Connection,这种情况是要加锁同步或者开事务的,会影响效率
试试改为一个线程一个Connection

#3


另外,每个线程回调函数开头都调用一下AfxOleInit();

#4


引用 3 楼 stjay 的回复:
另外,每个线程回调函数开头都调用一下AfxOleInit();


UINT Thread1(LPVOID lpParam)
{
CString str;
clock_t t_Start , t_End;


//初始化COM库
AfxOleInit();
//连接数据库
//建立数据库的连接需要使用Connection Object。步骤如下:
//定义一个_ConnectionPtr类型的指针,代码如下: 
//_ConnectionPtr m_pConnection;  
//调用CreateInstance方法实例化: 
//m_pConnection.CreateInstance(__uuidof(Connection));

CString strSQL;
HRESULT hr;
_ConnectionPtr m_pConnection; 
try
{
hr=m_pConnection.CreateInstance(__uuidof(Connection));
m_pConnection->CursorLocation=adUseClient;
strSQL="Provider=SQLOLEDB;Server=1104A01\\MSSQLSERVER1104;Database=DCS;UID=sa;PWD=726";
if(SUCCEEDED(hr))

hr=m_pConnection->Open(_bstr_t(strSQL),"","",adModeUnknown);

}

catch(_com_error e) //捕捉异常     
{
CString errormessage;
errormessage.Format(_T("连接数据库1失败!\r\n错误信息:%s",e.ErrorMessage()));
AfxMessageBox(errormessage);//显示错误信息

return FALSE;     
}
_CommandPtr m_pCommand;
try
{

m_pCommand.CreateInstance(__uuidof(Command));
m_pCommand->ActiveConnection = m_pConnection;
m_pCommand->CommandText="Insert_date_data";// 制定调用哪个存储过程
m_pCommand->CommandType=adCmdStoredProc;     // 制定Sql命令类型是存储过程
m_pCommand->Parameters->Refresh();

m_pCommand->Parameters->GetItem((long)1)->Value ="2013-03-13 21:34:50";//按存储过程的参数顺序给参数赋值
m_pCommand->Parameters->GetItem((long)2)->Value =100;
m_pCommand->Parameters->GetItem((long)3)->Value ="1234567890123456789012345678901234567890123456789012345678901234567890";
}

catch(_com_error e) //捕捉异常     
{
CString errormessage;
errormessage.Format(_T("连接数据库1失败!\r\n错误信息:%s",e.ErrorMessage()));
AfxMessageBox(errormessage);//显示错误信息

return FALSE;     
}
t_Start = clock();
m_pConnection->BeginTrans();
while(num--)
{
m_pCommand->Execute(0,0,adCmdStoredProc);
}
m_pConnection->CommitTrans();
t_End = clock();
str.Format("线程1所用时间为:%d",(t_End - t_Start));
::SetDlgItemText(AfxGetMainWnd()->m_hWnd,IDC_EDIT1,str);
Sleep(2000);
return 0;

在线程2中我定义了
_ConnectionPtr   m_pConnection2
_CommandPtr m_pCommand2
我用两个编辑框显示每个线程运行的时间,
但是每次只有一个线程能够运行结束,并显示运行时间,另一个线程一进运行数据一直没有写进数据库,这是为什么?有时候线程1正常,有时候线程2正常,求助啊...

#5


已经解决了,谢谢楼上的

#6


引用 3 楼 stjay 的回复:
另外,每个线程回调函数开头都调用一下AfxOleInit();

我两在两个线程向数据库写数据,为什么有些数据写不进数据库?会丢失一些数据?速度慢的时候,不会出现这种情况,一量MFC写的太快,数据库就丢数据,如何解决

#7


引用 6 楼 cekong126 的回复:
Quote: 引用 3 楼 stjay 的回复:

另外,每个线程回调函数开头都调用一下AfxOleInit();

我两在两个线程向数据库写数据,为什么有些数据写不进数据库?会丢失一些数据?速度慢的时候,不会出现这种情况,一量MFC写的太快,数据库就丢数据,如何解决


求解 问题该如何解决

#8


线程不同步的缘故