Accessing variables in multithreading

Hello,
I've got a variable, which is global: CDaoDatabase db;
I've got a function - it uses this variable.
I have a thread, which calls this function, which uses variable <db>.
It gives me an access violation when this function is getting called by thread(when I do db.Execute(SQL)), but it's not, when it's getting called by the program, which started the thread.
Can you help me, I need to use this variable - <db> when the function is been called from the thread. Why it dives me an access violation ?
Thanks.
MSafineAsked:
Who is Participating?
 
DanRollinsConnect With a Mentor Commented:
I think that these problems releate to the implicit calls to AfxDaoInit and AfxDaoTerm.  Try making implicit calls, from withing the thread.  This test works for me:

#include <afxdao.h>

UINT MyThreadProc( LPVOID pParam )
{
    AfxDaoInit();
    CDaoDatabase db1;
    db1.Open( "d:\\datasrcs\\world.mdb" );  
    AfxMessageBox("db open was called");
    db1.Close();
    AfxMessageBox("db close was called");
    AfxDaoTerm();
    return 0;   // thread completed successfully
}
void CD6Dlg::OnButton1()
{
   CWinThread* p= AfxBeginThread(MyThreadProc,0 );
}

=--==-=-=-=-=-=-=-
Most variations either cause errors either on attempting to use db1 fns  or when the program terminates.  

Note that AfxDaoTerm() modifies an app-global variable AfxGetApp()->m_lpfnDaoTerm, setting it to NULL.  When non-NULL, then in the normal MFC app termination calls the fn to which it points.  I'll guess that that address is invalid by the time that fn has been called.

Anyway, AfxGetApp()->m_lpfnDaoTerm is a singleton and it seems to be thread-specific.  I looked for warnings about this, but nothing popped out.  There is a discussion in technote 54 about using DAO in a DLL and other stuff.  That leads me to believe that these extra steps are needed.

If you can't create a per-thread copy of the DB, then I suggest switching to ODBC (or perhaps ADO or OLEDB) access to the database.  DAO is several generations old.

-- Dan
0
 
makerpCommented:
listening
0
 
nietodCommented:
Is the db object being used by two or more threads?  If so you must synchronize access to the object (usually) using a critical section.

For example, if the primary thread opens the database but the 2nd thread uses the db object, you need to insure that these two actions do not occur simultaneously.   In this case it would be possible to do this be opening the database from the 1st thread before even creating the 2nd thread.  But for more complex cases a synchronization device will be needed.

Otherwise we need to see the code.
0
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

 
makerpCommented:
the underlying database connection for CDatabase is thread safe, it is specified in the ODBC user guide and that is what it is built on (ODBC API calls). CDao... is tuned for Access and may not use ODBC

SqlAllocEnv for ODBC

"On operating systems that support multiple threads, applications can use the same henv on different threads and drivers must therefore support safe, multithreaded access to this information"

i would either move over to CDatabase (which will be better for portability between different databases, for example access -> oracle etc) or wrap all access to your database object in a critical section
0
 
makerpCommented:
i have looked through the code and i can not see ODBC calls in CDao's implementation
0
 
makerpCommented:
the MFC may have a problem with using the connection in a thread that does not own the object (the connection)..
0
 
nietodCommented:
>> the underlying database connection
>> for CDatabase is thread safe,
It would have to be.  It actualy has to be safe for access not only from multiple threads, but from multiple proccesses running on multiple machines.  

However you still need to syncronize access to the database object.  At least in terms of openeing and using the database, but almost certainly in terms of all operations.  (It is possible to make an object that would not require synchronization, but unless you know that was done, there is a good chance it wasn't done and you can't risk it.)

I definitely think we need to see the code...
0
 
makerpCommented:
yes, code will help, even though the database connection will be thread safe it is wrapped in an object, therefore other things in the object may not be thread safe, so yes critical sections.

also just out of interest try changing it tp CDatabase, then we can see if just a problem with CDao.

neitod, is there any chance the object could be coded in such a way as to only allow the thread that created it access it?

Paul
0
 
nietodCommented:
>> the object could be coded in such a way as
>> to only allow the thread that
>> created it access it?
Yes, but they woudl have to go to some trouble to do so, and for no apparent beneft so this is unlikely.  (I suppose its possible that there might actually be a benefit, it which case it could be likely, but I can't think of any.)
0
 
barzangyCommented:
I think that the function being called has to be reentrant. i.e it should be possible for two threads to call it without problems. this means that the object has to have reentrant methods.

Another possibility is to make the database connection inside the function and make the changes necessary with the help of parameters.

I hope this will help.
0
 
MSafineAuthor Commented:
In fact, this short peace of code with the databese is giving me the Access violation too, when the function is being called from the thread:

CDaoDatabase db1;
db1.Open(_T("db1.mdb"));  <-here the accesss violation.

When it's not being called from the thread, no problem.
The database was closed at that moment and so no any other object/function was using it.
This is very strange. It look like it's not recognizing that db1 is a database object. Also when it gives me a choice to debug, it takes me into assembley code.
0
 
nietodCommented:
We need to see the code.
0
 
makerpCommented:
i would move over to CDatabase and CRecordSet
0
 
barzangyCommented:
What I encountered once with threads was the fact that you put an object on the stack of the thread, I don't know how big is this object and whether calls to that object needs aome more stack. If the stack is too small you'll get an access violation indeed. so try to allocate the object on the heap like this:

CDaoDatabase * db1 = new CDaoDatabase();

And don't forget to free the heap memory at the end.

delete db1;
0
 
nietodCommented:
In win32 by default you start out with 1 meg of stack space per thread and that EXPANDS as needed.  I suspect that he/she is not running out of stack space.
0
 
MSafineAuthor Commented:
Thanks, it worked!
0
 
DanRollinsCommented:
I'm happy to help MSafine.  Thank goodness nobody locked this question with an answer.  Otherwise I'd have never seen it.

-- Dan
0
 
nietodCommented:
If someone had locked it with an answer, you wouldn't need to see it!
0
 
DanRollinsCommented:
>>If someone had locked it with an answer, you wouldn't need to see it!

Why? Because MSafine should be forced to find the solution "between the lines" in posts that don't even address the core issue?  

I think that EE Users deserve all of the help they can get from the experts that know how to research and solve such problems.  They don't need help from experts who only know how to click the [Answer] button.  But that is just one man's opinion.  Obviously, opinions vary here.

-- Dan
0
 
nietodCommented:
But if someone had answered the question who cares if you post to it or not?

If someone else has the answer why is it important that YOU be able to post the answer?  

>> They don't need help from experts who only
>> know how to click the [Answer]
If someone doesn't know the answer, they shouldn't be clicking the answer button.  If they do know the answer, then what is your problem?
0
 
DanRollinsCommented:
My mistake.  Thanks for correcting me.

-- Dan
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.