猿问

将COM事件从C#触发到C ++的正确方法是什么

我们有一个项目,其中包含许多C ++(使用ATL),VB6和最近的C#遗留代码。


我们最近将组件从C ++移植到了C#,该事件触发由C ++,VB6和C#中的组件处理的事件。从理论上讲,一切正常,但是触发事件会生成许多System.NotImplementedExceptions。


我已经修改了触发事件的代码,以便它分别调用每个事件处理程序,这样一个对象的异常不会阻止它在下一个对象中调用事件处理程序。


if ( GeneratedChannelChange != null )

{

  // Invoke each handler separately, so that an exception in one invokation does not prevent us calling the next one.

  foreach ( GeneratedChannelChangeEventHandler del in GeneratedChannelChange.GetInvocationList() )

  {

    try

    {

      del.Invoke ( GenChan, ChangeMask ) ;

    }

    catch  ( Exception ) {}

  }

}

实际上,由ATL向导生成的原始C ++代码也忽略了invoke函数返回的错误。


这似乎工作正常,但是我对它产生的大量异常不满意。在调试器中运行时,这也会降低性能。


我认为只有在C ++类中处理事件时才会引发异常。这是使用ATL类IDispEventSimpleImpl实现的。我发现的是,IDispEventSimpleImpl没有实现功能GetIDsOfNames。肯定会调用此函数,并且它将返回E_NOTIMPL。


可能是新的C#代码正在调用函数GetIDsOfNames,而旧的C ++代码没有吗?


如果是这样,是否有任何简单的方法可以在使用IDispEventSimpleImpl的类中实现功能GetIDsOfNames?


如果我的分析是错误的,是否有“正确”的方法在C#(作为事件源)和C ++(作为事件接收器)中实现事件逻辑?


慕工程0101907
浏览 299回答 1
1回答

偶然的你

我想,我已经解决了这一问题,通过更换IDispEventSimpleImpl的与IDispEventImpl的。这或多或少是一个即插即用的替代品,但是它确实需要引用类型库。ATL类继承了多个基类,包括一个定义为WorkspaceEventSink的基类。class ATL_NO_VTABLE CImportChannels :&nbsp; ...&nbsp; public WorkspaceEventSink,&nbsp; ...{&nbsp; &nbsp;...}先前定义为typedef IDispEventSimpleImpl< 42, CImportChannels, &DIID_ICs3WorkspaceEvents>&nbsp; &nbsp; &nbsp; &nbsp; WorkspaceEventSink ;我已将定义更改为typedef IDispEventImpl< 42, CImportChannels, &DIID_ICs3WorkspaceEvents, &LIBID_McAnalEventsNET, 1, 0 >&nbsp; &nbsp; &nbsp; &nbsp; WorkspaceEventSink ;除了将IDispEventSimpleImpl更改为IDispEventImpl外,我还添加了类型库的GUID及其主要版本号和次要版本号。最初,我尝试不使用主要版本号和次要版本号,但这导致了类型库未注册的异常。无需进行其他更改(例如对接收器映射进行更改)。
随时随地看视频慕课网APP
我要回答