Solved

COM CoInitializeEx(COINIT_MULTITHREADED) and AfxDAOInit

Posted on 1999-01-25
8
1,631 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Free Backup Tool for VMware and Hyper-V

Restore full virtual machine or individual guest files from 19 common file systems directly from the backup file. Schedule VM backups with PowerShell scripts. Set desired time, lean back and let the script to notify you via email upon completion.  

Question has a verified solution.

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

Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

630 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