Как сделать надежную асинхронную связь
Не используйте методы блокировки, у внутреннего вспомогательного класса есть некоторые тонкие ошибки.
Используйте APM с классом состояния сеанса, экземпляры которого управляют буфером и буферным курсором, совместно используемым между вызовами, и реализацией обратного вызова, которая включает EndRead
в try...catch
. При нормальной работе последнее, что должен сделать блок try
, - это установить следующий перекрывающийся обратный вызов ввода / вывода с вызовом BeginRead()
.
Когда дела идут плохо, catch
должен асинхронно вызывать делегата для метода перезапуска. Реализация обратного вызова должна завершиться сразу после блока catch
, чтобы логика перезапуска могла разрушить текущий сеанс (состояние сеанса почти наверняка повреждено) и создать новый сеанс. Метод перезапуска должен не быть реализован в классе состояния сеанса, потому что это предотвратит его разрушение и воссоздание сеанса.
Когда объект SerialPort закрыт (что произойдет при выходе из приложения), вполне может быть ожидающая операция ввода-вывода. Когда это так, закрытие SerialPort вызовет обратный вызов, и при этих условиях EndRead
сгенерирует исключение, которое неотличимо от общего дерьма посылки. Вы должны установить флаг в своем состоянии сеанса, чтобы запретить поведение перезапуска в блоке catch
. Это остановит ваш метод перезапуска от естественного выключения.
Можно полагаться на эту архитектуру, чтобы неожиданно не удерживать объект SerialPort.
Метод restart управляет закрытием и повторным открытием объекта последовательного порта. После того, как вы позвоните Close()
на SerialPort
объект, позвоните Thread.Sleep(5)
, чтобы дать ему возможность отпустить. Возможно, что-то еще захватит порт, поэтому будьте готовы с этим справиться, открывая его снова.