Последовательный порт, работающий в потоке с использованием MVP - PullRequest
0 голосов
/ 14 февраля 2012

У меня есть класс с именем SerialClient, который отправляет / получает байты через последовательный порт. Когда вызывается SerialClient.Start(), он входит в бесконечный цикл while, пока не будет вызван SerialClient.Stop(). У класса есть некоторые свойства, для простоты скажем SerialClient.PropA, SerialClient.PropB.

Мне нужно использовать это в графическом интерфейсе. Где в GUI вы можете вызывать Start, Stop и читать свойства по мере их изменения.

Чтобы использовать это в графическом интерфейсе, очевидно, SerialClient должен работать в потоке как его бесконечный цикл. Итак, я настроил вид со свойствами, соответствующими SerialClient. Представление вызывает Start() и Stop() на докладчике.

В докладчике я создаю новый поток и вызываю start для объекта SerialClient. Проблема заключается в том, что когда _serialClient генерирует исключение, презентатор не может его перехватить, а также, если такие свойства, как (SerialClient.PropB), изменяются и вызывают измененные обработчики событий, их необходимо вызывать в потоке графического интерфейса. Я попытался использовать фоновый рабочий, но не смог заставить его работать (изменение свойств все еще затрагивало пользовательский интерфейс из потока, не являющегося пользовательским интерфейсом).

Thread thread = new Thread(_serialClient.Start);
thread.IsBackground = true;
thread.Start();

Там должно быть простое решение, которое я смотрю. GUI просто нужно вызывать методы и читать свойства, а также предотвращать сбои исключений во всем приложении.

Есть идеи?

1 Ответ

1 голос
/ 16 февраля 2012

Вы столкнулись с 2 из общих проблем, обычно возникающих при работе с многопоточным приложением в C #:

  1. Работа с исключением в фоновом потоке.Когда в фоновом потоке возникают исключения, они перемещаются вверх по стеку от вызывающего к вызывающему, чтобы узнать, сможет ли кто-нибудь перехватить это исключение.Если исходный вызов происходит извне ваших собственных вызовов (например, обратный вызов с последовательного порта или таймера), вы можете или не можете быть уведомлены об исключении.В качестве типичного решения этой проблемы, я видел, чтобы обернуть в try-catch код, который может вызвать исключение, и чтобы обработчик события выдвинул исключение в поток, который сможет обработать исключение соответствующим образом (log,уведомить пользователя, прекратить, все вышеперечисленное)

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


 void someEvent_Handler(object sender, SomeEventEventArgs e)
{
    if (this.Dispatcher.CheckAccess())
    {
        // do work on UI thread
    }
    else
    {
        // or BeginInvoke()
        this.Dispatcher.Invoke(new Action(someEvent_Handler), 
            sender, e);
    }
}
 
...