c # .Net CF Form. Invoke поднять ArgumentException - PullRequest
1 голос
/ 04 августа 2009

Я получаю 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 ]

5 голосов
/ 04 августа 2009

Из статьи Msdn о событиях:

События - это особый вид многоадресной рассылки. делегат, который может быть вызван только из в классе или структуре, где они объявлены (класс издателя).

Это имеет смысл. Класс, который объявляет событие (издатель), должен быть единственным, кто определяет, когда и где происходит событие. По этой же причине событие предоставляет клиентскому коду (подписчику) только определенные операции, такие как подписка и отмена подписки.

В своем коде вы передаете событие DeviceResponseReceived в качестве аргумента делегата в targetForm.Invoke и ожидаете, что оно будет вызвано целью (Form). Цель не там, где объявлено событие, следовательно, исключение.

Вы хотите убедиться, что обработчик события DeviceResponse_DeviceResponseReceived выполняется в потоке пользовательского интерфейса, поскольку он, вероятно, касается компонентов пользовательского интерфейса. Тогда вы можете проверить, если InvokeRequired . Проверьте Поток пользовательского интерфейса WinForms Вызывает для получения дополнительной информации о том, как обновить пользовательский интерфейс из других потоков.

0 голосов
/ 04 августа 2009

Не испробовав код, одна вещь кажется мне странной в следующем коде:

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?

...