Исключение делегатов и перекрестных потоков - PullRequest
3 голосов
/ 20 апреля 2010

Всякий раз, когда я обновляю пользовательский интерфейс в форме Windows, используя делегат, это дает мне межпотоковое исключение почему так происходит? новый поток запускается для каждого вызова делегата?

void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
       //this call delegate to display data
       clsConnect(statusMsg);
}




 protected void displayResponse(string resp)
 {
     //here cross thread exception occur if directly set to lblMsgResp.Text="Test";
     if (lblMsgResp.InvokeRequired)
     {
        lblMsgResp.Invoke(new MethodInvoker(delegate { lblMsgResp.Text = resp; }));
     }
 }

Ответы [ 4 ]

5 голосов
/ 20 апреля 2010

Событие DataReceived имеет значение всегда , созданное в потоке потоков.Вы не можете обновить какой-либо элемент управления пользовательского интерфейса, у вас есть для использования Control.BeginInvoke ().Нет смысла тестировать InvokeRequired, это всегда так.

Здесь следует иметь в виду несколько вещей:

  • Не вызывайте Control.BeginInvoke для каждого отдельного символа или байтачто вы получаете.Это поставит поток пользовательского интерфейса на колени.Буферизуйте данные, которые вы получаете от последовательного порта, пока не получите полный ответ.Использование SerialPort.ReadLine () обычно работает хорошо, многие устройства отправляют строки, которые заканчиваются переводом строки (SerialPort.NewLine).
  • Завершение работы вашей программы может быть затруднено.Вы должны поддерживать форму, пока последовательный порт не перестанет отправлять.Получение события после закрытия формы сгенерирует исключение ObjectDisposed.Используйте событие FormClosing, чтобы закрыть последовательный порт и запустить таймер на одну секунду.Действительно закрывайте форму только по истечении таймера.
  • Избегайте использования Control.Invoke вместо BeginInvoke.Он может заблокировать вашу программу при вызове SerialPort.Close ().

Множество способов попасть в неприятности.Чтобы избежать их, рассмотрите возможность использования своего собственного потока вместо DataReceived.

2 голосов
/ 20 апреля 2010

Port_DataReceived, очевидно, является асинхронным обработчиком событий, который вызывается потоком в компоненте мониторинга портов.

есть ли новый поток для каждого вызов делегата?

Нет, наверное нет. Ваш компонент мониторинга портов выполняет опрос в фоновом потоке, и событие вызывается из этого потока каждый раз.

Дело в том, что он вызывается в потоке, отличном от пользовательского интерфейса, поэтому вам нужно будет использовать Control.Invoke и шаблоны, связанные с ним.

Подумайте об этом (и прочитайте пост , который может пролить свет на вас)

void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
   //this call delegate to display data
   UpdateTheUI(statusMsg);
}

private void UpdateTheUI(string statusMsg)
{
    if (lblMsgResp.InvokeRequired)
    {
        lblMsgResp.BeginInvoke(new MethodInvoker(UpdateTheUI,statusMsg));
    }
    else
    {
       clsConnect(statusMsg);
    }
}

С учетом всего сказанного я был бы упущен, если бы не указал, что косвенность вызывает беспокойство.

0 голосов
/ 20 апреля 2010

Межпотоковое исключение происходит, когда какой-либо ни один поток пользовательского интерфейса не изменяет элементы пользовательского интерфейса. Чтобы исправить это, используйте метод Invoke на самом элементе управления. В качестве дополнения вы можете проверить InvokeRequired на элементе управления перед вызовом метода Invoke. См MSDN

0 голосов
/ 20 апреля 2010

Исключение кросс-потока возникает, когда какой-либо ни один поток пользовательского интерфейса изменяет элементы пользовательского интерфейса.Поскольку элементы пользовательского интерфейса должны быть изменены только в потоке пользовательского интерфейса, это исключение выдается.Чтобы помочь вам понять, почему это происходит, вам придется опубликовать свой код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...