c#.Net CF Form.Invoke引发ArgumentException

时间:2009-08-04 10:10:06

标签: c# events compact-framework user-interface invoke

我从以下代码中收到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);
} 

感谢您花时间看看

2 个答案:

答案 0 :(得分:5)

来自Msdn article事件:

  

事件是一种特殊的多播   只能从中调用的委托   在他们的类或结构中   声明(发布者类)。

这是有道理的。声明事件(发布者)的类应该是唯一确定引发事件的时间和位置的类。这也是事件仅向客户端代码(订阅者)公开某些操作(如订阅和取消订阅)的原因。

在您的代码中,您将DeviceResponseReceived事件作为targetForm.Invoke中的委托参数传递,并期望它由目标(Form)调用。 Target不是声明事件的地方,因此也是例外。

您希望确保在UI线程上执行DeviceResponse_DeviceResponseReceived事件处理程序,因为它可以触及UI组件。然后在那里你可以检查InvokeRequired。查看WinForms UI Thread Invokes以获取有关如何从其他线程更新UI的更多信息。

答案 1 :(得分:0)

在没有尝试过代码的情况下,在下面的代码中有一件事让我感到奇怪:

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));
    }
}

您是否已分配DeviceResponseReceived委托(我假设它是?),然后您告诉targetForm调用该委托。代表实际上指向哪里?我猜你 想要做的是在targetForm中调用相应的方法?