2013-07-15 4 views
1

У меня есть последовательный порт, получающий данные от встроенного устройства асинхронно. У пользователя есть возможность прекратить соединение с портом в любое время, но это означает, что я получаю исключение, если пользователь отключает промежуточную передачу (иногда программа останавливается только на myPort.Close()). Есть ли способ добавить команду «Подождать до пустого»? Что-то вроде этого ниже?Как дождаться завершения последовательного порта до закрытия

private void tsDisconnect_Click(object sender, EventArgs e) 
{ 
     try 
     { 
      while(myPort.BytesToRead > 0) 
      {//wait here} 
     } 
     myPort.Close(); 
} 
+0

Какое исключение вы можете получить? Если пользователь отменяет операцию, вы всегда можете столкнуться с некоторыми ошибками, потому что вы не можете сказать, что данные пользователя полностью переданы или нет. – dwonisch

ответ

4

Ожидание не фиксирует тупик, который вы получаете от вызова Close(), вам необходимо устранить основную проблему. Это почти всегда вызвано кодом в обработчике событий DataReceived. Мы не видим этого, но очень распространенная ошибка заключается в использовании Control.Invoke() или Dispatcher.Invoke().

Последовательный порт не может закрыться до тех пор, пока обработчик события не вернется. Но он не может вернуться, потому что он застрял в вызове Invoke(). Что не может завершиться, потому что ваш поток пользовательского интерфейса занят, он застрял в вызове Close(). Или ждет BytesToRead, чтобы добраться до 0, решение, которое вы преследуете. Не будет работать, обработчик событий DataReceived застревает и больше не читает. Тупиковый город.

Вам нужно будет исправить этот код и вместо него использовать BeginInvoke(). Это неблокирующий вызов, он не может вызвать тупик.

Есть и другие возможные причины тупика. Легко диагностировать, у вас есть много времени для его отладки :) Используйте Debug + Break All, затем Debug + Windows + Threads. Дважды щелкните главный поток и посмотрите на стек вызовов, чтобы узнать, что делает поток пользовательского интерфейса.

+0

Ха-ха, ты меня прибил. 'myPort.Read (faultCodeData, 0, 1); this.Invoke (новый EventHandler (showFaultCode)); ' – tmwoods

+0

Я изменю это. Спасибо :) – tmwoods

+0

Зацените для психической отладки. Будьте осторожны, EventHandler вряд ли будет работать правильно. Вам необходимо передать копию данных. Он не будет использоваться до тех пор, пока вы не захотите убедиться, что данные все еще действительны, когда код работает в потоке пользовательского интерфейса. Переменная * faultCodeData * может быть перезаписана к тому времени. –

Смежные вопросы