C++ 什么';触发COM事件时,Lock()/Unlock()调用的目的是什么?

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

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连接=静态_转换(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";