Solved

COM CoInitializeEx(COINIT_MULTITHREADED) and AfxDAOInit

Posted on 1999-01-25
8
1,593 Views
Last Modified: 2013-11-25
I've following Microsoft's documentation, for dealing with DAO when you have a secured database.  You basically have to initialize Dao yourself with AfxDaoInit(), and then setup to system MDW for access security.

I'm trying to do this in a Out of Process Com server (EXE), that has called CoInitializeEx(COINIT_MULTITHREADED) to provided a multi-threading COM interface.  This server is a singleton.

The problem is that AfxDaoInit() calls CoInitialize() which calls CoInitialize().  Microsoft documents that CoInitialize() simply calls CoInitializeEx(COINIT_APARTMENTTHREADED).

By calling this, it attempts to change the threading model after initialization and returns an error.  This is a documented error condition.

This problem did not show up until I installed NT Service Pack 4, which I guess properly detects the threading model change.

My question is, how does one use Dao within a multi-threaded out of process com server?  The design of the object is thread safe, DOA is only called and used during an initialization process that is run only once.

0
Comment
Question by:rmichels
  • 4
  • 4
8 Comments
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 1185116
You are probably better off served creating a separate thread that calls CoInitialize() and do all of the DAO stuff in there.
0
 
LVL 3

Author Comment

by:rmichels
ID: 1185117
Sorry, but your answer is the crux of the problem.  Once on thread has called CoInitializeEx(), that thread or any other thread cannot call CoInitializeEx() with a different threading model.

In my program, one thread has started the Server and called CoInitializeEx(), another thread has issued a second CoInitialize()..which errors out.
0
 
LVL 15

Accepted Solution

by:
Tommy Hui earned 100 total points
ID: 1185118
"Once on thread has called CoInitializeEx(), that thread or any other thread cannot call CoInitializeEx() with a different threading model."

This is not true. A thread can enter and leave any COM apartment as long as it properly exits an apartment before entering a different one. In a thread, you can call CoInit as many times as possible. Here is a program (designed for VC for simplicity):

#define _WIN32_WINNT 0x400
#include <windows.h>
#include <ole2.h>
#include <tchar.h>
#include <stdio.h>

#pragma comment(lib, "ole32.lib")

int main(int argc, char* argv[])
{
      HRESULT hr;

      hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
      if (FAILED(hr))
      {
            _tprintf(_T("CoInit apartment failed 1. \n"));
      }

      // success
      hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
      if (FAILED(hr))
      {
            _tprintf(_T("CoInit apartment failed 2. \n"));
      }

      CoUninitialize();

      // Final call to leave apartment
      //
      CoUninitialize();

      // Switch apartments
      //
      hr = CoInitializeEx(0, COINIT_MULTITHREADED);
      if (FAILED(hr))
      {
            _tprintf(_T("CoInit multi failed 1. \n"));
      }

      hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
      if (FAILED(hr))
      {
            _tprintf(_T("CoInit apartment failed 3. \n"));
      }

      // Since only CoInit succeeded
      //
      CoUninitialize();

      return 0;
}

If you run this program, you should see the output: CoInit apartment failed 3. The reason is the main thread is trying to switch COM apartments without properly exiting the apartment first.

In your application, you can have the main thread be in one COM apartment and in your second thread be in another COM apartment. While COM does allow this, it takes more effort to get it right. So you can have your main thread do all of its regular stuff and have a secondary thread and initializes DAO with its own apartment.

0
Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

 
LVL 3

Author Comment

by:rmichels
ID: 1185119
While techinically correct, I don't think your answer helps me, but I'll ask for more information.  The COM Server is an Out of Process EXE server.  On it's main startup, it initializes itself to a Multi Threaded server.  Also this com object is a singleton.  One server for many clients.  So the main thread of the EXE has initialized to Multi Threaded.  When a Client comes in and wants to do some processing, it calls AfxDaoInit, which calls CoInitialize().  This client is on a separate thread.  The CoInitializeFails.  

I don't see how I can uninitialize the first Thread, without breaking the COM interface?  The only uninitialize I do, is when the server is exiting.
0
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 1185120
When the client comes into your server, you can create another thread and wait for the thread to finish. The other thread initializes COM to be single apartment and initializes DAO. It can then do your queries and deinitializes DAO and COM and returns. The client thread can then continue executing with the returned data.

0
 
LVL 3

Author Comment

by:rmichels
ID: 1185121
True, your response is correct and I realize design changes can help the problem, but does not answer the more basic question:

My question is, how does one use Dao within a multi-threaded out of process com server?  Any help there?





0
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 1185122
The trouble with DAO is that in MFC, you are stuck to their model. If you install the DAOSDK, you'll find the dbDao classes which are infinitely more flexible. They will let you initialize to different apartments. The DAOSDK is included on your VC++ CDROM.

If you are familiar with the MFC classes, the dbDao classes are really easy to pick up.
0
 
LVL 3

Author Comment

by:rmichels
ID: 1185123
I'll give your latest comment a try.  Thanks for all your comments!


0

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
What my article will show is if you ever had to do processing to a listbox without being able to just select all the items in it. My software Visual Studio 2008 crystal report v11 My issue was I wanted to add crystal report to a form and show…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question