Link to home
Start Free TrialLog in
Avatar of sinister
sinister

asked on

Problems with CDaoDatabase and multiple threads

Hello,

I am writing a program that handles database operations for a IVR telephone system. I have numerous threads running that handle the db operations. The problem is that when many calls hangup at the same time my program has to log information to an Access database the threads crash on the open database call. I use a global critical section object around the code and I open the database in exclusive non-shared mode but still there are crashes. Note, that this works for a few hours under heavy stress but eventually crashes.

My question is that, has anyone encountered such problems with MFC Dao classes. Also, does AfxDaoInit and AfxDaoTerm have to always be called before and after any database operations? These functions seem to create their own threads and I have a feeling that they are screwing up. The crash seems to happen inside the Dao350.dll because when I click on the "Cancel" button on the famous Access Violation window MSStudio opens up with Dao350.dll dissambeley.

Please, let me know if this question is understandable. Any help would be appreciated. Thanks.
Avatar of Nicolay_Ch
Nicolay_Ch

MSDN say, that AfxDaoInit you should call before working with database...

and AfxDaoTerm you program should call automatically, but I see, tham my program not call it, and I call it manually...
Database always has one or other problems when used in threads
Call AfxDaoInit() in EACH thread you created and AfxDaoTerm() only once in your application clean-up code.


Also you need to call AfxDaoInit() if you use callback functions.

Hope this helps
Avatar of sinister

ASKER

Currently I am opening, running query, and then closing the database, do I have to call AfxDaoInit before I do the database open?
If you do it in your main application thread then NO

If you do it in separate thread or callback functions you need to call AfxDaoInit() BEFORE any call to DAO functions in the current thread.

If you want to access the Jet database from a multithreaded app, then I'll suggest that you switch to OLEDB instead.

OLEDB has full support for multithreaded access to the database.

Take a look at the classes CDataSource, CSession, CRowset.

Here is an example of opening a jet database using OLEDB:

HRESULT TestFunction()
{
    CDataSource ds;
    CSession session;

    wchar_t* pwcPath = "C:\\MyData.mdb";

    CDBPropSet dbinit(DBPROPSET_DBINIT);
    dbinit.AddProperty(DBPROP_INIT_DATASOURCE, pwcPath);
    dbinit.AddProperty(DBPROP_INIT_MODE, (long)(DB_MODE_READWRITE));
    dbinit.AddProperty(DBPROP_INIT_PROMPT, (short)DBPROMPT_NOPROMPT);
    dbinit.AddProperty(DBPROP_INIT_LCID, (long)GetSystemDefaultLCID());
    dbinit.AddProperty(DBPROP_AUTH_USERID, OLESTR("Admin"));
    dbinit.AddProperty(DBPROP_AUTH_PASSWORD, OLESTR(""));
   
#if(USE_JET_VERSION==40)
    hr = ds.Open(CLSID_JETOLEDB_4_00, &dbinit);
#else
    hr = ds.Open(CLSID_JETOLEDB_3_51, &dbinit);
#endif
    if(FAILED(hr))
        return hr;
   
    hr = session.Open(ds);
    if(FAILED(hr))
        return hr;


    //
    // ... Do something with it ...
    // ....



    session.Close();
    ds.Close();

    return S_OK;
}
Can someone tell me if MFC's CDatabase class is thread safe, it would be much easier for me change my code to CDatabase from CDaoDatabase rather than OLE DB or ADO.
Yes MFC's CDatabase and CRecordset is thread-safe classes. YOu can use them in separate threads without any kind of additional preparations for that.
Greetings,

Can someone tell me how I can get rid of the CDatabase object when I am done with it. Here is an abbreviation of the code:

CDatabase * oDb = new CDatabase;
CRecordset rs(oDb);

// run some querries

rs.Close();
oDb->Close();
delete oDb;

However, when my function returns I get an exception because the pointer that CDatabase uses is still valid. This exception happens inside CObject.

Thanks.

By the way, who wants the points
ASKER CERTIFIED SOLUTION
Avatar of vachooho
vachooho
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Great thanks for everything. I decided to use a global database object for all threads and then protect any query executions with critical secitons. I had to minimize the amount of opens and closes because memory was jumping up like crazy. I am still having crashes if implement transaction processing. Are there any problems with using ODBC to get at MS ACCESS rather than DAO. I am using CDatabase so I can have many threads query the db asynchronously