2011-07-07 91 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

感谢您在这里的帮助。我想你已经为我解决了这个问题。 –

相关问题