C++ 什么';触发COM事件时,Lock()/Unlock()调用的目的是什么?
ATL COM服务器中典型的代码触发事件如下所示(复制并稍微修剪):C++ 什么';触发COM事件时,Lock()/Unlock()调用的目的是什么?,c++,events,visual-c++,com,atl,C++,Events,Visual C++,Com,Atl,ATL COM服务器中典型的代码触发事件如下所示(复制并稍微修剪): HRESULT Fire\u MessageTrigger() { HRESULT hr=S_正常; T*pThis=静态施法(本); int count=m_vec.GetSize(); for(int i=0;iLock();//我在问这个。。。 CComPtr punkConnection=m_vec.GetAt(i); pThis->Unlock();//还有这个 IDispatch*p连接=静态_转换(punkCon
HRESULT Fire\u MessageTrigger()
{
HRESULT hr=S_正常;
T*pThis=静态施法(本);
int count=m_vec.GetSize();
for(int i=0;iLock();//我在问这个。。。
CComPtr punkConnection=m_vec.GetAt(i);
pThis->Unlock();//还有这个
IDispatch*p连接=静态_转换(punkConnection.p);
如果(pConnection==0)
继续;
DISPPARAMS params={NULL,NULL,0,0};
hr=pConnection->Invoke(2,IID为空,区域设置为用户默认,
DISPATCH_方法和参数,0,NULL,NULL);
}
返回人力资源;
}
调用
Lock()
和Unlock()
的目的是什么?它是围绕m_vec
成员变量(接收器列表)的线程安全措施
您可以在并发线程上执行以下操作:
template <class T, const IID* piid, class CDV>
STDMETHODIMP IConnectionPointImpl<T, piid, CDV>::Advise(
_Inout_ IUnknown* pUnkSink,
_Out_ DWORD* pdwCookie)
{
// ...
pT->Lock();
*pdwCookie = m_vec.Add(p); // <<--- Modifying m_vec here
hRes = (*pdwCookie != NULL) ? S_OK : CONNECT_E_ADVISELIMIT;
pT->Unlock();
早期的VS版本可以生成无锁代码,并且只有当您从VS IDE手动重新生成代理类时,代码才会更新。好的,我还看到了类似的代码,这些代码不
lock()
/Unlock()
。如果服务器应该支持并发,那么所有事件触发代码都应该Lock()
/Unlock()
当前对象,这样说是否正确?这都是关于线程安全的。有时需要锁定,有时不需要。在任何时候,您都有兴趣在尽可能短的时间内保持锁定状态。还请注意,对于STA base(CComSingleThreadModel
),这些调用解析为空方法而不生成代码。假设我有十个COM类,它们具有相同的线程模型,而不是主STA,并且每个类都支持一些事件,它们都是使用IConnectionPointImpl
实现的。我是否需要在所有问题中都使用这种锁定?也许您想为您的最后一个问题提供一个更具体的示例。因为这些Lock
/Unlock
s保护对m_vec
成员的访问(这个实例的成员!不管您在项目中有多少类和实例),然后在另一个场景中,我们可能会谈论一件完全不同的事情。嗯,我理解这一点。假设我有十节课。。。(如上面的评论中所示)-仅在其中一些中使用此锁定而在其他中不使用此锁定是否有意义?
template <class T, const IID* piid, class CDV>
STDMETHODIMP IConnectionPointImpl<T, piid, CDV>::Advise(
_Inout_ IUnknown* pUnkSink,
_Out_ DWORD* pdwCookie)
{
// ...
pT->Lock();
*pdwCookie = m_vec.Add(p); // <<--- Modifying m_vec here
hRes = (*pdwCookie != NULL) ? S_OK : CONNECT_E_ADVISELIMIT;
pT->Unlock();
strProxyMethod +=
"\t\tfor (int iConnection = 0; iConnection < cConnections; iConnection++)\r\n"+
"\t\t{\r\n"+
"\t\t\tpThis->Lock();\r\n"+
"\t\t\tCComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);\r\n"+
"\t\t\tpThis->Unlock();\r\n\r\n";