Проблема с SerialPort - PullRequest
       3

Проблема с SerialPort

7 голосов
/ 12 июля 2010

Я работаю с SerialPort для связи (только для чтения) со считывателем штрих-кода.

Я установил драйвер для работы со считывателем, как если бы он был подключен через Com-порт, хотя это USB-устройство.Когда устройство подключено, в списке появляется еще один Com-порт.

Проблема заключается в следующем.Я инициализирую объект SerialPort для чтения из считывателя штрих-кода, но если считыватель отключен, у меня нет возможности правильно завершить или утилизировать объект SerialPort, поскольку порт, к которому он «подключен», больше не существует.

Результатом является WinIOException, когда программа закрывается.Я не могу поймать это не только в коде, работающем с SerialPort, но и на уровне program.cs.Согласно стеку, WinIOException генерируется после попыток завершить и утилизировать объект SerialPort.

Есть какие-нибудь идеи, как мне правильно работать в этой ситуации?Или, по крайней мере, поймать исключение?

Я точно знаю, что проблема не в этом конкретном драйвере;У меня был еще один считыватель штрих-кода от другого производителя (с тем же драйвером назначения) - ситуация та же.

Ответы [ 6 ]

12 голосов
/ 12 июля 2010

Вздох, это давняя проблема с эмуляторами последовательного порта USB.Последовательные порты - это устройства, которые датируются каменным веком.Раньше их вкручивали в шину, и их нельзя было убрать, пока программа использовала их, не создавая искр и вздымающегося дыма.Каменный век также включает в себя отсутствие какой-либо поддержки plug-and-play, чтобы программа могла обнаружить, что устройство внезапно превратилось в гонзо.

К сожалению, большинство драйверов устройств, которые имитируют их, просто делают ихисчезнуть, даже если программа открыла порт.Это работает примерно так же, как и извлечение флэш-накопителя из гнезда, когда Windows записывает на него файлы.Существует фоновый рабочий поток, который ожидает уведомлений от драйвера устройства, чтобы он мог генерировать события DataReceived, ErrorReceived и PinChanged.Этот поток переносит сердечный приступ, когда устройство внезапно исчезает.Вы не можете поймать это, это поток, который был запущен классом SerialPort, вы не можете обернуть его с помощью try / catch.

По многочисленным просьбам Microsoft что-то сделала с этим в .NET 4.0.Не совсем уверен, что происходит в этом выпуске.Если вы застряли в более раннем выпуске, единственное разумное, что вы можете сделать, это прикрепить знак рядом со слотом USB: «Не удаляйте во время использования!»Что неизбежно заставляет кого-то отключить устройство, по крайней мере, дважды, чтобы увидеть, что происходит.После чего им это надоедает, и вы оставляете вас в покое.

Весьма необоснованный обходной путь - файл app.exe.config с таким содержанием:

<?xml version ="1.0"?>
<configuration>
  <runtime>
    <legacyUnhandledExceptionPolicy enabled="1"/>
  </runtime>
</configuration>

Не используйте его

5 голосов
/ 19 сентября 2011

В моем коде это происходит как часть метода Finalize() в BaseStream, который вызывается сборщиком мусора.

Таким образом, если один наследует класс .NET SerialPort и переопределяет Open/ Закрыть, вы можете сделать следующее:

Во время открытия, просто позвоните GC.SuppressFinalize(Me.BaseStream)

Во время закрытия, попробуйте позвонить GC.ReRegisterForFinalize(Me.BaseStream)

Если USB имеетвытащил, это вызовет исключение, стонет о доступе к BaseStream.Либо проверьте свойство .IsOpen перед вызовом GC, либо оберните его в Try Catch, если вы не доверяете .IsOpen в возврате False каждый раз ...

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

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

2 голосов
/ 12 июля 2010

Вы можете наследовать от SerialPort и переопределить метод Dispose () для обработки таких исключений. Вы можете просто проглотить исключение (утилизировать не следует, в любом случае).

Если вы хотите зарегистрировать исключение или обработать его каким-либо другим способом, сначала вам нужно будет проверить флаг , утилизирующий . Если значение равно false, это означает, что Dispose был вызван деструктором SerialPort, а объект уже потерян.

1007 * Е.Г. *

    public class MySerialPort:SerialPort
    {
        protected override void Dispose(bool disposing)
        {
            try
            {
                base.Dispose(disposing);
            }
            catch (Exception exc )
            {                    
                if (disposing)
                {
                    //Log the error
                }
            }

        }
    }
1 голос
/ 27 апреля 2017

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

TLDR; Создайте отдельный процесс.

Пример кода

Код процесса последовательного порта

static void Main(string[] args)
{
    using (var output = Console.OpenStandardOutput())
    using (var serialPort = new SerialPort(args[0], int.Parse(args[1])))
    {
        serialPort.Open();
        while (serialPort.IsOpen)
        {
            serialPort.BaseStream.CopyTo(output);
        }
    }
}

Основное применение

var options = new ProcessStartInfo()
{
    FileName = "Serial Port Process name here",
    UseShellExecute = false,
    RedirectStandardOutput = true,
};

using(var process = Process.Start(options))
{
    using (StreamReader reader = process.StandardOutput)
    {
        while (!process.HasExited)
        {
            string result = reader.ReadLine();
            Console.WriteLine(result);
        }
    }
}
0 голосов
/ 06 ноября 2013

У меня был такой же опыт.Хотя это не рекомендуется, вы можете отключить и подключить последовательное устройство к фактическому последовательному порту, и связь начнется снова.Последовательный порт USB не работает таким образом.У меня также была проблема с тем, что последовательный порт USB не отображается как доступный порт методом SerialPort.GetPortNames () до тех пор, пока программное обеспечение не создаст виртуальный последовательный порт.

0 голосов
/ 20 июля 2010

Ну, плохие новости.

Решение от Panagiotis Kanavos не помогаетПроблема все еще здесь.

.Net 4.0 тоже не помогает.Я установил VS2010 - ничего не изменилось.Неискаженное исключение все еще выброшено.К сожалению, «наклеить знак рядом со слотом USB:« Не удаляйте во время использования! »Кажется единственным решением ...

...