2011-07-07 4 views
0

は、私は次のように開始されたCOMサーバーを持っている:複数のクライアントが、それが要求を(関数は、COMオブジェクトへの呼び出しを処理しないこのCOMサーバーに接続している場合複数のクライアントが接続されたWindows Com Serverはマルチスレッドで接続されていますか?

extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, 
    HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/) 
{ 
    lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT 

#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED) 
    HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED); 
#else 
    HRESULT hRes = CoInitialize(NULL); 
#endif 
    _ASSERTE(SUCCEEDED(hRes)); 
    _Module.Init(ObjectMap, hInstance, &LIBID_EXACTACONSOLIDATIONLib); 
    _Module.dwThreadID = GetCurrentThreadId(); 
    TCHAR szTokens[] = _T("-/"); 

    int nRet = 0; 
    BOOL bRun = TRUE; 
    LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens); 
    while (lpszToken != NULL) 
    { 
     if (lstrcmpi(lpszToken, _T("UnregServer"))==0) 
     { 
      _Module.UpdateRegistryFromResource(IDR_ExactaConsolidation, FALSE); 
      nRet = _Module.UnregisterServer(TRUE); 
      bRun = FALSE; 
      break; 
     } 

     if (lstrcmpi(lpszToken, _T("RegServer"))==0) 
     { 
      _Module.UpdateRegistryFromResource(IDR_ExactaConsolidation, TRUE); 
      nRet = _Module.RegisterServer(TRUE); 
      bRun = FALSE; 
      break; 
     } 

     lpszToken = FindOneOf(lpszToken, szTokens); 
    } 
    if (bRun) 
    { 
     _Module.StartMonitor(); 

     #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED) 

     hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, 
      REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED); 
     _ASSERTE(SUCCEEDED(hRes)); 
     hRes = CoResumeClassObjects(); 

     #else 

     hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, 
      REGCLS_MULTIPLEUSE); 

     #endif 

     _ASSERTE(SUCCEEDED(hRes)); 

     MSG msg; 
     while (GetMessage(&msg, 0, 0, 0)) 
      DispatchMessage(&msg); 

     _Module.RevokeClassObjects(); 
     Sleep(dwPause); //wait for any threads to finish 
    } 
} 

私の質問はそのCOMサーバー同期ファッションでは?

私が尋ねる理由は、次のシナリオは次のとおりです。 クライアントがクライアントBは両方コムサーバーCに接続します。彼らは両方ともリクエストを発行し、このリクエストはCOMオブジェクトを使用して次のアイテム(私の場合は注文)をデータベースから取得することを伴います。 2つのクライアントに同じアイテムを持たせるべきではないので、基本的に何が起きるかは、各アイテムがデータベースから取得されてクライアントに返されたときにマークされるものとしてマークされます。

は、それが同じCOMサーバーに接続する2つのクライアントだ場合について競合状態を気にせずに撮影したとして、データベース内のアイテムをマークするために、上記のシナリオでは、それは十分ですか?リクエストが処理された場合、と同時に私は、これをアイテムにマークしただけでいいと思います。

答えて

4

これは、クラスオブジェクトを登録する(または、むしろ作成する)スレッドがシングルスレッドアパートメントかマルチスレッドアパートメントかによって異なります。 MSDN article on the threading modesを参照してください。 CoInitialize(NULL)またはCoInitializeEx(NULL, COINIT_APARTMENTTHREADED)でCOMを初期化した場合は、STAに参加しています。 CoInitializeEx(NULL, COINIT_MULTITHREADED)またはCoInitializeEx(NULL, 0)を使用した場合は、MTAに参加しています。

MTAを使用している場合、COMはスレッドプールから同時にオブジェクトに複数の呼び出しを行います。 STAでは、一度に1つの通話のみが行われます。レースを避けたいのであれば、STAの使用は合理的なアプローチになります。ただし、これによりパフォーマンスのボトルネックが発生することに注意してください。非常に大量のサーバーや要求がかかるサーバーでは、独自の同期ロジックを使用するMTAを使用する方が望ましい場合があります。

+0

+1非常に良い点。上記の方程式に欠落したコードを追加しました。私がデバッグ(Win XP)していたとき、それはSTA(CoInitialize(NULL);)にありました。 –

+0

@Coleなので、 '_WIN32_WINNT> = 0x0400&defined(_ATL_FREE_THREADED)'の場合はMTAに入ります。だから、あなた自身の同期を入れたり、STAに強制する必要があります – bdonlan

+0

ここで助けてくれてありがとう。私はあなたがこれをまっすぐに整えたと思う。 –