我正在InvalidCastException
将 EventHandler`1 投射到之前运行过的代码中的 EventHandler ,并且我知道没有相关内容变化。 (我有新旧版本。)
有趣的是我一直使用这种类型。 我不明白为什么甚至会将EventHandler`1扩展到EventHandler。请参阅附带的源摘录:
基础是这样的:
Option Strict On
Option Explicit On
Option Infer Off
Public Class CapturedEventArgs
Inherits EventArgs
Property Handled As Boolean
Property Processor As clsScannerProcessor
Property Scan As String
End Class
Public Class clsScannerProcessor
Public Event CapturedInProcessor As EventHandler(Of CapturedEventArgs)
'executed in background thread
Sub EvaluateScan()
'excerpt: ... on valid scan pattern
Dim cea As New CapturedEventArgs() With {.Scan = _scan,
.Processor = Me,
.Handled = False}
_mainContext.Send(AddressOf RaiseCapturedInProcessorEvent, cea) 'EXCEPTION HERE
End Sub
'executed in main thread
Private Sub RaiseCapturedInProcessorEvent(e As Object)
RaiseEvent CapturedInProcessor(Me, DirectCast(e, CapturedEventArgs))
End Sub
End Class
请知道为什么这些类型在运行时突然不兼容?在我没有对继承类型进行任何更改之前,代码工作正常。
我添加的内容是此类事件的自定义事件中继。据我了解,它不应该相关。
完整的例外文字:
System.InvalidCastException was unhandled
Message=Unable to cast object of type 'System.EventHandler`1[myProject.clsScannerProcessor+CapturedEventArgs]' to type 'System.EventHandler'.
Source=System.Windows.Forms
StackTrace:
at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
at System.Windows.Forms.WindowsFormsSynchronizationContext.Send(SendOrPostCallback d, Object state)
at vpsCRMsql.clsScannerProcessor.EvaluateScan() in ...
at vpsCRMsql.clsScannerProcessor.EvaluateKeystroke(stQueuedEvent keyEvent) in ...
at vpsCRMsql.clsScannerProcessor.WatchQueue() in ...
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
整体模型:
多个设备处理器(在不同的线程中运行)引发自己的事件,这些事件将转发到事件中继以引发一个公共事件。
事件中继(在 clsScannerManager 类中管理上述 clsScannerProcessor 的一个或多个实例)如下所示:
Public Class clsScannerManager
Public Custom Event Captured As EventHandler(Of clsScannerProcessor.CapturedEventArgs)
AddHandler(ByVal value As EventHandler(Of clsScannerProcessor.CapturedEventArgs))
_eventReceivers.Add(value)
End AddHandler
RemoveHandler(value As EventHandler(Of clsScannerProcessor.CapturedEventArgs))
_eventReceivers.Remove(value)
End RemoveHandler
RaiseEvent(sender As Object, e As clsScannerProcessor.CapturedEventArgs)
For Each handler As EventHandler In _eventReceivers
'some more complex work in here
Next
End RaiseEvent
End Event
Sub AddEventToProcessor(processor As clsScannerProcessor)
AddHandler processor.CapturedInProcessor, AddressOf RaiseCapturedEvent
End Sub
Sub RaiseCapturedEvent(sender As Object, e As clsScannerProcessor.CapturedEventArgs)
RaiseEvent Captured(sender, e)
End Sub
答案 0 :(得分:1)
只是一个预感,但应该看起来像这样:
For Each handler As EventHandler In _eventReceivers
实际上看起来像这样
For Each handler As EventHandler(Of clsScannerProcessor.CapturedEventArgs) In _eventReceivers
和
Private _eventReceivers As New ArrayList()
实际上应该是这样的:
Private _eventReceivers As New List(Of EventHandler(Of clsScannerProcessor.CapturedEventArgs))
您获得的例外来自For Each行。变量_eventReceivers有一组对象,它们的类型为EventHandler(Of clsScannerProcessor.CapturedEventArgs),尽管引用实际上存储为对象。无法将EventHandler(of clsScannerProcessor.CapturedEventArgs)强制转换为EventHandler,因此抛出了强制转换异常。通过WindowsFormsSynchronizationContext.Send的调用会截断调用堆栈。
答案 1 :(得分:0)
我为学习目的添加了这个答案。
棘手的部分是代码中VS 2012中抛出异常的地方:
_mainContext.Send(AddressOf RaiseCapturedInProcessorEvent, cea) 'EXCEPTION HERE
实际问题是RaiseCapturedInProcessorEvent
调用内部的几个级别(并且它在接受的答案中显示的很明显),但异常未在Send()
之前显示
InvalidCastException
误导我认为Send()
参数存在问题。