我从以下代码中收到一个 ArgumentException,我很难理解它,堆栈跟踪中的最后一个条目是
System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr,
Binder binder, Object[] parameters, CultureInfo culture,
Boolean verifyAccess, StackCrawlMark& stackMark)
当我逐步执行时,DeviceResponse 已按预期填充,目标已按预期定位,但 targetForm.Invoke 每次都会抛出
如有任何帮助,我们将不胜感激。
事件定义为:
public static event EventHandler<MsgEventArgs<DeviceResponse>> DeviceResponseReceived;
事件是从此代码引发的:
//Raise the event
if (DeviceResponseReceived != null)
{
if (DeviceResponseReceived.Target is System.Windows.Forms.Form)
{
System.Windows.Forms.Form targetForm = DeviceResponseReceived.Target as System.Windows.Forms.Form;
targetForm.Invoke(DeviceResponseReceived, new MsgEventArgs<DeviceResponse>(deviceResponse));
}
}
MsgEventArgs 是从 EventArgs 派生的通用事件参数类:
public class MsgEventArgs<T> : EventArgs
{
public MsgEventArgs(T value)
{
m_value = value;
}
private T m_value;
public T Value
{
get { return m_value; }
}
}
在我的表单中,我已经在表单构造函数中注册了事件:
DeviceResponse.DeviceResponseReceived += new EventHandler<MIASmartClient.Messaging.Transport.MsgEventArgs<DeviceResponse>>(DeviceResponse_DeviceResponseReceived);
实现如下:
void DeviceResponse_DeviceResponseReceived(object sender, MIASmartClient.Messaging.Transport.MsgEventArgs<DeviceResponse> e)
{
_presenter.DeviceResponseReceived(e.Value);
}
感谢您抽出时间来看
最佳答案
来自Msdn article关于事件:
Events are a special kind of multicast delegate that can only be invoked from within the class or struct where they are declared (the publisher class).
这是有道理的。声明事件的类(发布者)应该是唯一确定事件何时何地引发的类。这也是为什么事件只向客户端代码(订阅者)公开某些操作,例如订阅和取消订阅。
在您的代码中,您将 DeviceResponseReceived 事件作为委托(delegate)参数传递给 targetForm.Invoke 并期望它被目标(表单)调用。目标不是声明事件的地方,因此是异常。
您要确保 DeviceResponse_DeviceResponseReceived 事件处理程序在 UI 线程上执行,因为它可能会接触 UI 组件。然后在那里你可以检查是否 InvokeRequired .查看WinForms UI Thread Invokes有关如何从其他线程更新 UI 的更多信息。
关于c# .Net CF Form.Invoke 引发 ArgumentException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1226680/