Multithreading and ADO

  • Thread starter Thread starter Chandhru
  • Start date Start date
C

Chandhru

Hi,

I am creating multiple threads to access a database and retrieve
records using ADO. I am getting runtime error "abnormal program
termination'.

My main() function creates an Database connection and recordset
object. it also creates multiple thread which accesses ThreadFunc() .
it passes the recordset object to ThreadFunc().

ThreadFunc() function receives the recordset object prints the
record and moves the pointer to the next record.

I am attaching the code below. please correct me.

Code:
#import "C:\Program files\Common Files\System\Ado\msado15.dll"
no_namespace rename("EOF", "ADOEOF")

#include <windows.h>
#include <stdio.h>
#include <ole2.h>
#include <conio.h>

#define NUM_THREADS 12

CRITICAL_SECTION cs;
HRESULT hr;
_ConnectionPtr pConn;
_RecordsetPtr pRs;

/*
ThreadFunc is responsible for accessing the Recordset. and moving
through
recordset.
*/
DWORD WINAPI ThreadFunc(LPVOID lpParam)
{
EnterCriticalSection(&cs);
_bstr_t val = pRs->Fields->Item[_variant_t("BTN")]->Value;
printf("%s\n",(char*)val);
pRs->MoveNext();
//printf("Hello World, I'm thread# %d\n", (int)lpParam);
//printf("hello world \n");
LeaveCriticalSection(&cs);
return 0;
}//ThreadFunc

void main(){

DWORD dwThreadId;
HANDLE hThread[NUM_THREADS];
int n;
CoInitialize(NULL);
InitializeCriticalSection(&cs);
// Create an ADO connection to database
try{
hr = pConn.CreateInstance(__uuidof(Connection));
hr = pRs.CreateInstance(__uuidof(Recordset));
_bstr_t
strConn("Provider=sqloledb;server=SINF005;Trusted_Connection=yes;database=Core;");
pConn->Open(strConn,"","",adConnectUnspecified);
pRs->Open("SELECT top 10 Npa_Num from Npa (NOLOCK)",
pConn.GetInterfacePtr(), adOpenForwardOnly, adLockReadOnly,
adCmdText);
//pRs->Open("SELECT BTN from mbs_GetSpitFireEasyPay (NOLOCK)",
pConn.GetInterfacePtr(), adOpenForwardOnly, adLockReadOnly,
adCmdText);
}catch(_com_error &e){
printf("Error\n");
printf("\tCode meaning = %s", e.ErrorMessage());
}

// create all the threads
for (n = 0; n < NUM_THREADS; n++)
{
hThread[n] = CreateThread(NULL, 0, ThreadFunc, &pRs, 0,
&dwThreadId);
if (hThread == NULL)
fprintf(stderr, "Failed to create thread# %d", n);
}//for
for (n = 0; n < NUM_THREADS; n++)
{
if (hThread[n] != NULL)
WaitForSingleObject(hThread[n], INFINITE);
}//for

DeleteCriticalSection(&cs);
printf("This is after all threads exited\n");
CoUninitialize();
}

Thanks
 
The problem is with your threading model. According to the MSDN
documentation:

"[CoInitialize] initializes the COM library on the current thread and
identifies the concurrency model as single-thread apartment (STA)."

Essentially, when an object is created in a single-threaded apartment, it
can and should only be accessed directly by the thread that created it. Any
other thread that needs to make calls into it must use a technique called
interface marshalling, which allows is to make thread-safe calls using a
proxy/stub paradigm.

I don't believe the ADO library is designed to be thread-safe, because it
usually doesn't even make sense for more than one thread to access the same
recordset simultaneously. If you simply want the recordset operations to
happen on a background thread, simply have that thread be the one that
creates the recordset object (and remember to call CoInitialize and
CoUninitialize within the thread proc).

Mike

Chandhru said:
Hi,

I am creating multiple threads to access a database and retrieve
records using ADO. I am getting runtime error "abnormal program
termination'.

My main() function creates an Database connection and recordset
object. it also creates multiple thread which accesses ThreadFunc() .
it passes the recordset object to ThreadFunc().

ThreadFunc() function receives the recordset object prints the
record and moves the pointer to the next record.

I am attaching the code below. please correct me.

Code:
#import "C:\Program files\Common Files\System\Ado\msado15.dll"
no_namespace rename("EOF", "ADOEOF")

#include <windows.h>
#include <stdio.h>
#include <ole2.h>
#include <conio.h>

#define NUM_THREADS 12

CRITICAL_SECTION cs;
HRESULT hr;
_ConnectionPtr pConn;
_RecordsetPtr pRs;

/*
ThreadFunc is responsible for accessing the Recordset. and moving
through
recordset.
*/
DWORD WINAPI ThreadFunc(LPVOID lpParam)
{
EnterCriticalSection(&cs);
_bstr_t val = pRs->Fields->Item[_variant_t("BTN")]->Value;
printf("%s\n",(char*)val);
pRs->MoveNext();
//printf("Hello World, I'm thread# %d\n", (int)lpParam);
//printf("hello world \n");
LeaveCriticalSection(&cs);
return 0;
}//ThreadFunc

void main(){

DWORD dwThreadId;
HANDLE hThread[NUM_THREADS];
int n;
CoInitialize(NULL);
InitializeCriticalSection(&cs);
// Create an ADO connection to database
try{
hr = pConn.CreateInstance(__uuidof(Connection));
hr = pRs.CreateInstance(__uuidof(Recordset));
_bstr_t
 strConn("Provider=sqloledb;server=SINF005;Trusted_Connection=yes;database=Co
re;");
pConn->Open(strConn,"","",adConnectUnspecified);
pRs->Open("SELECT top 10 Npa_Num from Npa (NOLOCK)",
pConn.GetInterfacePtr(), adOpenForwardOnly, adLockReadOnly,
adCmdText);
//pRs->Open("SELECT BTN from mbs_GetSpitFireEasyPay (NOLOCK)",
pConn.GetInterfacePtr(), adOpenForwardOnly, adLockReadOnly,
adCmdText);
}catch(_com_error &e){
printf("Error\n");
printf("\tCode meaning = %s", e.ErrorMessage());
}

// create all the threads
for (n = 0; n < NUM_THREADS; n++)
{
hThread[n] = CreateThread(NULL, 0, ThreadFunc, &pRs, 0,
&dwThreadId);
if (hThread == NULL)
fprintf(stderr, "Failed to create thread# %d", n);
}//for
for (n = 0; n < NUM_THREADS; n++)
{
if (hThread[n] != NULL)
WaitForSingleObject(hThread[n], INFINITE);
}//for

DeleteCriticalSection(&cs);
printf("This is after all threads exited\n");
CoUninitialize();
}

Thanks
 
Just to add to Mike's post, an alternative to marshalling the interface is
to have each thread enter the process' MTA by calling CoInitializeEx(NULL,
COINIT_MULTITHREADED). This would be useful if you want to maintain your
paradigm of one thread managing the connection and other threads utilizing
the recordsets.

--
John Phillips
MVP - Windows SDK



Chandhru said:
Hi,

I am creating multiple threads to access a database and retrieve
records using ADO. I am getting runtime error "abnormal program
termination'.

My main() function creates an Database connection and recordset
object. it also creates multiple thread which accesses ThreadFunc() .
it passes the recordset object to ThreadFunc().

ThreadFunc() function receives the recordset object prints the
record and moves the pointer to the next record.

I am attaching the code below. please correct me.

Code:
#import "C:\Program files\Common Files\System\Ado\msado15.dll"
no_namespace rename("EOF", "ADOEOF")

#include <windows.h>
#include <stdio.h>
#include <ole2.h>
#include <conio.h>

#define NUM_THREADS 12

CRITICAL_SECTION cs;
HRESULT hr;
_ConnectionPtr pConn;
_RecordsetPtr pRs;

/*
ThreadFunc is responsible for accessing the Recordset. and moving
through
recordset.
*/
DWORD WINAPI ThreadFunc(LPVOID lpParam)
{
EnterCriticalSection(&cs);
_bstr_t val = pRs->Fields->Item[_variant_t("BTN")]->Value;
printf("%s\n",(char*)val);
pRs->MoveNext();
//printf("Hello World, I'm thread# %d\n", (int)lpParam);
//printf("hello world \n");
LeaveCriticalSection(&cs);
return 0;
}//ThreadFunc

void main(){

DWORD dwThreadId;
HANDLE hThread[NUM_THREADS];
int n;
CoInitialize(NULL);
InitializeCriticalSection(&cs);
// Create an ADO connection to database
try{
hr = pConn.CreateInstance(__uuidof(Connection));
hr = pRs.CreateInstance(__uuidof(Recordset));
_bstr_t
 strConn("Provider=sqloledb;server=SINF005;Trusted_Connection=yes;database=Co
re;");
pConn->Open(strConn,"","",adConnectUnspecified);
pRs->Open("SELECT top 10 Npa_Num from Npa (NOLOCK)",
pConn.GetInterfacePtr(), adOpenForwardOnly, adLockReadOnly,
adCmdText);
//pRs->Open("SELECT BTN from mbs_GetSpitFireEasyPay (NOLOCK)",
pConn.GetInterfacePtr(), adOpenForwardOnly, adLockReadOnly,
adCmdText);
}catch(_com_error &e){
printf("Error\n");
printf("\tCode meaning = %s", e.ErrorMessage());
}

// create all the threads
for (n = 0; n < NUM_THREADS; n++)
{
hThread[n] = CreateThread(NULL, 0, ThreadFunc, &pRs, 0,
&dwThreadId);
if (hThread == NULL)
fprintf(stderr, "Failed to create thread# %d", n);
}//for
for (n = 0; n < NUM_THREADS; n++)
{
if (hThread[n] != NULL)
WaitForSingleObject(hThread[n], INFINITE);
}//for

DeleteCriticalSection(&cs);
printf("This is after all threads exited\n");
CoUninitialize();
}

Thanks
 
-----Original Message-----
Hi,

I am creating multiple threads to access a database and retrieve
records using ADO. I am getting runtime error "abnormal program
termination'.

My main() function creates an Database connection and recordset
object. it also creates multiple thread which accesses ThreadFunc() .
it passes the recordset object to ThreadFunc().

ThreadFunc() function receives the recordset object prints the
record and moves the pointer to the next record.

I am attaching the code below. please correct me.

Code:
#import "C:\Program files\Common Files\System\Ado\msado15.dll"
no_namespace rename("EOF", "ADOEOF")

#include <windows.h>
#include <stdio.h>
#include <ole2.h>
#include <conio.h>

#define NUM_THREADS 12

CRITICAL_SECTION cs;
HRESULT hr;
_ConnectionPtr pConn;
_RecordsetPtr pRs;

/*
ThreadFunc is responsible for accessing the Recordset. and moving
through
recordset.
*/
DWORD WINAPI ThreadFunc(LPVOID lpParam)
{
EnterCriticalSection(&cs);
_bstr_t val = pRs->Fields->Item[_variant_t ("BTN")]->Value;
printf("%s\n",(char*)val);
pRs->MoveNext();
//printf("Hello World, I'm thread# %d\n", (int) lpParam);
//printf("hello world \n");
LeaveCriticalSection(&cs);
return 0;
}//ThreadFunc

void main(){

DWORD dwThreadId;
HANDLE hThread[NUM_THREADS];
int n;
CoInitialize(NULL);
InitializeCriticalSection(&cs);
// Create an ADO connection to database
try{
hr = pConn.CreateInstance(__uuidof (Connection));
hr = pRs.CreateInstance(__uuidof (Recordset));[QUOTE]
_bstr_t
strConn[/QUOTE]
("Provider=sqloledb;server=SINF005;Trusted_Connection=yes;d
atabase=Core;");[QUOTE]
pConn->Open[/QUOTE]
(strConn,"","",adConnectUnspecified);
pRs->Open("SELECT top 10 Npa_Num from Npa (NOLOCK)",
pConn.GetInterfacePtr(), adOpenForwardOnly, adLockReadOnly,
adCmdText);
//pRs->Open("SELECT BTN from[/QUOTE]
mbs_GetSpitFireEasyPay (NOLOCK)",[QUOTE]
pConn.GetInterfacePtr(), adOpenForwardOnly, adLockReadOnly,
adCmdText);
}catch(_com_error &e){
printf("Error\n");
printf("\tCode meaning = %s", e.ErrorMessage());
}

// create all the threads
for (n = 0; n < NUM_THREADS; n++)
{
hThread[n] = CreateThread(NULL, 0, ThreadFunc, &pRs, 0,
&dwThreadId);
if (hThread == NULL)
fprintf(stderr, "Failed to create thread# % d", n);
}//for
for (n = 0; n < NUM_THREADS; n++)
{
if (hThread[n] != NULL)
WaitForSingleObject(hThread[n], INFINITE);
}//for

DeleteCriticalSection(&cs);
printf("This is after all threads exited\n");
CoUninitialize();
}

Thanks
.
 
Back
Top