我有一个 Windows 窗体应用程序,它使用共享类来容纳应用程序的所有常见对象。设置类有一组定期做事的对象,然后有一些有趣的事情,他们需要提醒主窗体并让它更新。
我目前正在通过对象上的事件来执行此操作,并且在创建每个对象时,我添加一个 EventHandler 以将事件映射回表单。但是,我遇到了一些麻烦,这表明这些请求并不总是最终出现在我的表单的主副本上。例如,我的表单有一个通知托盘图标,但是当表单捕获和事件并尝试显示气泡时,没有出现气泡。但是,如果我修改该代码以使图标可见(尽管它已经可见),然后显示气泡,则会出现第二个图标并正确显示气泡。
有没有人遇到过这个?有没有一种方法可以强制我的所有事件被表单的单个实例捕获,或者是否有完全不同的方法来处理这个?如有必要,我可以发布代码示例,但我认为这是一个常见的线程问题。
更多信息:我目前在表单的事件处理程序中使用 Me.InvokeRequired,在这种情况下它总是返回 FALSE。此外,当我从该表单中使其可见时创建的第二个托盘图标没有上下文菜单,而“真实”图标有 - 这是否提示任何人?
我要拔头发了!这不可能那么难!
解决方案:感谢 nobugz 提供的线索,它引导我找到我现在正在使用的代码(它工作得很好,虽然我不禁想到有更好的方法来做到这一点)。我向名为“IsPrimary”的表单添加了一个私有布尔变量,并将以下代码添加到表单构造函数中:
Public Sub New()
If My.Application.OpenForms(0).Equals(Me) Then
Me.IsFirstForm = True
End If
End Sub
一旦设置了这个变量并且构造函数完成,它直接进入事件处理程序,我以这种方式处理它(CAVEAT:由于我正在寻找的表单是应用程序的主要表单,My.Application.OpenForms( 0) 得到我需要的东西。如果我正在寻找非启动表单的第一个实例,我必须遍历直到找到它):
Public Sub EventHandler()
If Not IsFirstForm Then
Dim f As Form1 = My.Application.OpenForms(0)
f.EventHandler()
Me.Close()
ElseIf InvokeRequired Then
Me.Invoke(New HandlerDelegate(AddressOf EventHandler))
Else
' Do your event handling code '
End If
End Sub
首先,它检查它是否在正确的表单上运行——如果不是,则调用正确的表单。然后它检查线程是否正确,如果不正确则调用 UI 线程。然后它运行事件代码。我不喜欢这可能是三个电话,但我想不出另一种方法来做到这一点。它似乎工作得很好,虽然它有点麻烦。如果有人有更好的方法,我很想听听!
再次感谢所有的帮助——这让我发疯了!