2011-07-07 61 views
0

我有一個是通過以下方式啓動一個COM服務器:Windows Com服務器是否有多個客戶端連接多線程?

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服務器它處理請求(函數調用COM對象的COM服務器正在託管)同步時尚?

我想問的原因是因爲以下情形的: 客戶端A客戶端B都連接到的COM服務器C。他們都發出一個請求,這個請求涉及到使用COM對象從數據庫中檢索下一個項目(在我的情況下命令)。沒有兩個客戶應該被允許擁有相同的項目,所以基本上發生的是每個項目在從數據庫中檢索並返回給客戶時被標記爲被採用。

是否足以在上述案例數據庫中的項目標記爲已拍攝,而不用擔心比賽條件,如果是2個客戶端連接到同一COM服務器?如果請求同步處理我認爲這可能是好的,只需將該項目標記爲已採用。

回答

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中,一次只能撥打一個電話。如果你只是想避免比賽,使用STA可能是一個合理的方法;請記住,這會造成性能瓶頸,但是,對於數量很大的服務器或請求可能需要一段時間的服務器,使用帶有自己的同步邏輯的MTA可能更可取。

+0

+1非常好的一點。我在上面的公式中添加了缺少的代碼。當我調試時(Win XP)它在STA(CoInitialize(NULL);)。 –

+0

@Cole,所以如果'_WIN32_WINNT> = 0x0400&defined(_ATL_FREE_THREADED)',你就進入MTA。所以你需要把自己的同步,或強制它成爲一個STA – bdonlan

+0

感謝您在這裏的幫助。我想你已經爲我解決了這個問題。 –

相關問題