具有多个客户端连接的Windows Com Server 是多线程的吗?
我有一个以以下方式启动的 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 Server C。它们都发出一个请求,并且该请求涉及使用 COM 对象从数据库中检索下一个项目(在我的例子中是订单)。不允许两个客户端拥有相同的项目,因此基本上发生的情况是,从数据库检索每个项目并将其返回给客户端时,将其标记为已获取。
在上述场景中,如果有 2 个客户端连接到同一 COM 服务器,则将数据库中的项目标记为已获取是否足够,而不必担心竞争条件?如果请求同步处理,我认为只需将项目标记为已采取就可以了。
I have a com server that is started in the following way:
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
}
}
My question is if multiple clients are connected to this COM Server does it process the requests (function calls to the com object that the com server is hosting) in a synchronous fashion?
The reason I ask is because of the following scenario:
Client A and Client B both connect to Com Server C. They both issue a request and this request involves using the COM Object to retrieve the next item (order in my case) from the database. No two clients should be allowed to have the same item so what basically happens is each item is marked as taken when it's retrieved from the database and returned to the client.
Is it sufficient in the scenario above to mark the item in the database as taken without worrying about race conditions if it's 2 clients connecting to the same COM server? If the requests are processed synchronously I would think this would be ok to just mark the item as taken.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这取决于注册(或者更确切地说,创建)类对象的线程是单线程单元还是多线程单元。请参阅有关线程模式的 MSDN 文章。如果您使用
CoInitialize(NULL)
或CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)
初始化 COM,则您处于 STA 状态;如果您使用了CoInitializeEx(NULL, COINIT_MULTITHREADED)
或CoInitializeEx(NULL, 0)
,则您处于 MTA 中。如果您在 MTA 中,COM 将从线程池中同时对您的对象进行多次调用。在 STA 中,一次只能进行一次调用。如果你只是想避免竞争,使用 STA 可能是一个合理的方法;但请记住,这会造成性能瓶颈,因此对于容量非常大的服务器或请求可能需要一段时间的服务器,使用具有您自己的同步逻辑的 MTA 可能更好。
This depends on whether the thread registering (or, rather, creating) the class objects is a Single Threaded Apartment or Multi-Threaded Apartment. See the MSDN article on the threading modes. If you initialized COM with
CoInitialize(NULL)
orCoInitializeEx(NULL, COINIT_APARTMENTTHREADED)
, you're in a STA; if you usedCoInitializeEx(NULL, COINIT_MULTITHREADED)
orCoInitializeEx(NULL, 0)
, you're in a MTA.If you're in a MTA, COM will make multiple calls to your objects at the same time from a thread pool. In a STA, only one call will be made at a time. If you just want to avoid races, using a STA can be a reasonable approach; keep in mind that this will create a performance bottleneck, however, so for very high volume servers, or servers where requests may take a while, using a MTA with your own synchronization logic may be preferable.