15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


DAO 'multithread' - interesting problem

David Ohlssen -- DAVIDO@COMMERCE.CTECH.AC.ZA
Tuesday, May 14, 1996

NT 4.0.1234 VC++4.0 

I know DAO is not multithread re-entrant. (Yet? Ever?)   I have a
worker thread that mans the comms port and has to write records to
disk as they come in.   The user app has to display some of that
data, perhaps older records, but according to user request.   I have
made a second worker thread that has sole control over the DAO db
recordsets.  Both the comms thread and the CView supply and retrieve
data by asking the db thread via the pointers. The communication is
via flag-pointers and data in the CWinApp class, located via
AfxGetApp().  The db thread opens the database and closes it when
there is a signal from exitinstance.  Exit instance waits for the
threads to signal completion then calls the default.   There are
judicius Sleep calls in every waiting situation.

When exitinstance calls the default there is an access violation.  I 
have traced and found that it calls AfxDaoTerm() which crashes in 
the call to RemoveAll() workspaces.   The actual crash is because of 
m_pBlocks containing zero and being used as a pointer in MFC code.
Is this because the db thread opened the database and we are letting 
CWinApp clean up (the main app thread)?  It can't be, because the 
pointer to AfxDaoTerm is set for the main thread otherwise it wouldnt 
be called.  I NEED the separate db thread, to provide rapid service to 
the comms thread regardless of user activity such as listbox fill.

I have tried using the CDaoDatabase class on the stack and heap and
in the app.    I have tried a 5 second sleep before calling the
default ExitInstance().   Even with no daorecordsets being opened it
crashes.  If I comment out the CDaoDatabase::Open and Close lines,
it does not crash.   A non-thread version of a similar program works
fine with similar DAO structure, except that the database variables
are in the CDocument and the close is triggered by
CView::DestroyWindow().
The worker control functions are normal global functions (not 
classes), inside the app source file for convenience.   


David O. Ohlssen
I  _____________________________________  I
I  | Davido@Commerce.CTech.ac.ZA       |  I
I  |    __  ____________               |  I
I  |   /  \/ Cape Town  \  _           |  I
I  |__/     South Africa \/ \__________|  I
I_________________________________________I



MCVICAR DAVID ugrad -- com50008@paisley.ac.uk
Thursday, May 16, 1996

[Mini-digest: 2 responses]

David Ohlssen wrote:
> 
> NT 4.0.1234 VC++4.0
> 

> I have tried using the CDaoDatabase class on the stack and heap and
> in the app.    I have tried a 5 second sleep before calling the
> default ExitInstance().   Even with no daorecordsets being opened it
> crashes.  If I comment out the CDaoDatabase::Open and Close lines,
> it does not crash.   A non-thread version of a similar program works
> fine with similar DAO structure, except that the database variables
> are in the CDocument and the close is triggered by
> CView::DestroyWindow().

I experienced similar problems when doing something similar in a console
based Win32 based server.  I traced through the MFC code and found that
unless there was a CWinApp available that there was an exception.  This
was due to DAO trying to call the App to get a pointer to a function to
shutdown the Jet engine.  By adding an unused CWinApp class I solved
this.  It is possible that with the multiple threads accessing DAO that
once one of the threads is killed that it shuts down the Jet database
engine, when you then try to access it again you would get the exception
you talk of.  This is only a suggestion and mayt be wrong but this
definitely happened in a console based app.  Possibly this is one for
the FAQ ?

-- 
David A. McVicar

EMail: dmcvicar@bcs.org.uk / com50008@paisley.ac.uk
Phone - Home  : 01505 322099 - Anytime before 22:00
	Mobile: 0973 386463  - Anytime

-----From: Dan Kirby 

Hi,

DAO can only be used in the primary thread of an application.  This 
information comes straight from the DAO developers.  You must remember that 
DAO is a technology which comes from the VB/Access products which support 
applications with a single primary thread.  That is the only way by which 
DAO has been tested.

Some folks have been able to get things to work if they use the dbDAO C++ 
classes from the DAO SDK and don't intialize OLE in any other thread except 
the thread which uses DAO but, again, it really was never tested with that 
in mind.

The DAO team is looking at making DAO at least apartment model in the 
future but there have been no timeframes announced for this.  One key 
problem is that DAO uses the Jet engine and that is not thread-safe so the 
DAO group probably won't do much until the underlying db engine changes  to 
allow thread safety.

The MFC problem you are seeing is because MFC performs a DAO call from the 
primary thread to Release the DBEngine object but the object was created in 
a different thread.   To do this, an OLE object must follow OLE apartment 
threading rules which DAO does not.

--dan



Brian Jones -- BrianJ@ats-nt.apptechsys.com
Monday, May 20, 1996


Is CDatabase an effective workaround for this problem?

 ----------
From:  owner-mfc-l[SMTP:owner-mfc-l@netcom.com]
Sent:  Thursday, May 16, 1996 5:44 PM
To:  mfc-l
Subject:  Re: DAO "multithread" - interesting problem

[Mini-digest: 2 responses]

David Ohlssen wrote:
>
> NT 4.0.1234 VC++4.0
>

> I have tried using the CDaoDatabase class on the stack and heap and
> in the app.    I have tried a 5 second sleep before calling the
> default ExitInstance().   Even with no daorecordsets being opened it
> crashes.  If I comment out the CDaoDatabase::Open and Close lines,
> it does not crash.   A non-thread version of a similar program works
> fine with similar DAO structure, except that the database variables
> are in the CDocument and the close is triggered by
> CView::DestroyWindow().

I experienced similar problems when doing something similar in a console
based Win32 based server.  I traced through the MFC code and found that
unless there was a CWinApp available that there was an exception.  This
was due to DAO trying to call the App to get a pointer to a function to
shutdown the Jet engine.  By adding an unused CWinApp class I solved
this.  It is possible that with the multiple threads accessing DAO that
once one of the threads is killed that it shuts down the Jet database
engine, when you then try to access it again you would get the exception
you talk of.  This is only a suggestion and mayt be wrong but this
definitely happened in a console based app.  Possibly this is one for
the FAQ ?

 --
David A. McVicar

EMail: dmcvicar@bcs.org.uk / com50008@paisley.ac.uk
Phone - Home  : 01505 322099 - Anytime before 22:00
        Mobile: 0973 386463  - Anytime

 -----From: Dan Kirby 

Hi,

DAO can only be used in the primary thread of an application.  This
information comes straight from the DAO developers.  You must remember   
that
DAO is a technology which comes from the VB/Access products which support   

applications with a single primary thread.  That is the only way by which   

DAO has been tested.

Some folks have been able to get things to work if they use the dbDAO C++   

classes from the DAO SDK and don't intialize OLE in any other thread   
except
the thread which uses DAO but, again, it really was never tested with   
that
in mind.

The DAO team is looking at making DAO at least apartment model in the
future but there have been no timeframes announced for this.  One key
problem is that DAO uses the Jet engine and that is not thread-safe so   
the
DAO group probably won't do much until the underlying db engine changes   
 to
allow thread safety.

The MFC problem you are seeing is because MFC performs a DAO call from   
the
primary thread to Release the DBEngine object but the object was created   
in
a different thread.   To do this, an OLE object must follow OLE apartment   

threading rules which DAO does not.

 --dan




| Вернуться в корень Архива |