【发布时间】:2013-01-03 22:49:44
【问题描述】:
主窗体是否有某种方法可以在不参考引发事件的 ClassB 的特定实例的情况下侦听 ClassB 的自定义事件的任何引发?
将生成事件的 ClassB 实例当前在表单知道的 ClassA 实例中匿名实例化。
(最终更新:我直接调用 MainForm 方法没有按预期工作的原因是在接受的答案 to this question。)
更新我怀疑它比我想象的要复杂。以下引用解释了为什么我对 MainForm.DataReady() 的调用不起作用 - 以一种令人发狂的模糊方式。
.NET 事件的魔力隐藏了这样一个事实,即当您通过 A 的实例订阅 B 的实例中的事件时,A 会被发送到 B 的 appdomain。如果 A 不是 MarshalByRef,则发送 A 的值副本。现在您有两个单独的 A 实例,这就是您遇到意外行为的原因。
Cross AppDomain MarshallByRef vs value copy discussion
更新2:
使用:
Debug.WriteLine("SetWaitState executing with Id={0}", AppDomain.CurrentDomain.Id)
在MainForm 本地事件处理程序的上下文中执行MainForm.DataReady() 并从ClassB 调用时显示它们每次都在相同的AppDomain 中运行。这使得不同的线程成为问题的原因——然而MainForm.InvokeRequired 在每种情况下都返回 false。它仍然没有意义——但至少自定义事件——根据需要冒泡——确实有效。
下面的代码说明了这些关系。
Class MainForm
private A as New ClassA
private sub getData
A.getData() 'Sets up the com object & callback
end sub
Private Sub _ClassB_HandleEvent(ResultMessage As String) Handles {some static/shared reference to ClassB}.CustomEvent
'do something with the Message
End Sub
End Class
Class ClassA
public sub getData()
Dim ComObj as New ComObject
Call ComObj.setClient(New ClassB)
End Sub
End Class
Class ClassB
Implements IComObjectClient
Public Event CustomEvent(ByVal ResultMessage As String)
sub getdata_callback(results() as Object) handles IComObjectClient.getdata_callback
' Get the results
RaiseEvent CustomEvent("Got Data") 'because calling MainForm.DataReady() doesn't work
end sub
End Class
【问题讨论】:
-
这是不可能的。事件是由对象而不是类引发的。您可以为所有对象赋予相同的事件处理程序,使用 AddHandler + AddressOf 关键字。但这通常会导致流泪,因为 COM 事件不会打扰传递类似于 sender 参数的任何内容。
标签: .net vb.net delegates event-handling com-interop