Как сделать надежное программирование SerialPort с .NET / C #?

Указатель NULL - это тот, который указывает на никуда. Когда вы разыскиваете указатель p, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p является нулевым указателем, местоположение, хранящееся в p, является nowhere, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception.

В общем, это потому, что что-то не было правильно инициализировано.

26
задан Thomas Kjørnes 14 January 2009 в 01:19
поделиться

9 ответов

@thomask

Да, Hyperterminal действительно включает fAbortOnError в DCB SetCommState, что объясняет большинство исключений IOExceptions, создаваемых объектом SerialPort. Некоторые ПК / карманные компьютеры также имеют UART, у которых по умолчанию включен флаг прерывания при ошибке, поэтому обязательно, чтобы процедура инициализации последовательного порта очищала его (что Microsoft не сделала). Недавно я написал длинную статью, чтобы объяснить это более подробно (см. this , если вам интересно).

24
ответ дан 28 November 2019 в 07:37
поделиться

Вы не можете закрыть кого-то elses соединение с портом, следующий код никогда не будет работать:

if (serialPort.IsOpen) serialPort.Close();

, поскольку Ваш объект не открыл порт, Вы не можете закрыть его.

Также необходимо закрыть и расположить последовательный порт даже после того, как исключения происходят

try
{
   //do serial port stuff
}
finally
{
   if(serialPort != null)
   {
      if(serialPort.IsOpen)
      {
         serialPort.Close();
      }
      serialPort.Dispose();
   }
}

, Если Вы хотите, чтобы процесс был прерываем тогда, необходимо Проверить, открыт ли порт и затем обратно прочь в течение периода, и затем попробуйте еще раз, что-то как.

while(serialPort.IsOpen)
{
   Thread.Sleep(200);
}
4
ответ дан trampster 14 January 2009 в 01:19
поделиться
  • 1
    @EliKonky. Хорошая работа. Хорошо работает. У меня есть вопрос. Я хочу скрыть индикатор выполнения после того, как он достигнет 100 (макс. значение). Как установить его видимость, за которой следуют, это достигает макс.? Выручите меня. – Nitesh Khatri 1 August 2015 в 18:52

Я попытался изменить поток работы как это с тем же самым результатом. Как только HyperTerminal однажды преуспевает в том, чтобы "получить порт" (в то время как мой поток спит), мой сервис не будет в состоянии открыть порт снова.

public void DoorOpener()
{
    while (true)
    {
        SerialPort serialPort = new SerialPort();
        Thread.Sleep(1000);
        serialPort.PortName = "COM1";
        serialPort.BaudRate = 9600;
        serialPort.DataBits = 8;
        serialPort.StopBits = StopBits.One;
        serialPort.Parity = Parity.None;
        try
        {
            serialPort.Open();
        }
        catch
        {
        }
        if (serialPort.IsOpen)
        {
            serialPort.DtrEnable = true;
            Thread.Sleep(1000);
            serialPort.Close();
        }
        serialPort.Dispose();
    }
}
1
ответ дан slavoo 14 January 2009 в 01:19
поделиться
  • 1
    если кто-либо хочет анимировать вторичный прогресс, тогда изменяются в классе progressBar.setSecondaryProgress((int)value); ProgressBarAnimation вместо progressBar.setProgress((int) value); – Zahidul 8 May 2018 в 06:57

Вы попытались оставить порт открытым в Вашем приложении, и просто повернуть DtrEnable вкл\выкл, и затем закрыть порт, когда Ваше приложение закрывается? т.е.:

using (SerialPort serialPort = new SerialPort("COM1", 9600))
{
    serialPort.Open();
    while (true)
    {
        Thread.Sleep(1000);
        serialPort.DtrEnable = true;
        Thread.Sleep(1000);
        serialPort.DtrEnable = false;
    }
    serialPort.Close();
}

я не знаком с семантикой DTR, таким образом, я не знаю, работало ли это.

2
ответ дан FryGuy 14 January 2009 в 01:19
поделиться
  • 1
    что получат значения interpolatedTime??? это, зависят к значению, которое u устанавливал для setDuration ()??? – hamid_c 18 January 2016 в 15:42

Этот код, кажется, работает правильно. Я протестировал его на своей локальной машине в консольном приложении, с помощью Procomm Плюс открыться/закрыть порт, и программа продолжает отсчитывать.

    using (SerialPort port = new SerialPort("COM1", 9600))
    {
        while (true)
        {
            Thread.Sleep(1000);
            try
            {
                Console.Write("Open...");
                port.Open();
                port.DtrEnable = true;
                Thread.Sleep(1000);
                port.Close();
                Console.WriteLine("Close");
            }
            catch
            {
                Console.WriteLine("Error opening serial port");
            }
            finally
            {
                if (port.IsOpen)
                    port.Close();
            }
        }
    }
1
ответ дан slavoo 14 January 2009 в 01:19
поделиться
  • 1
    должен быть ofInt;-) и вероятно от 0 до 100 (но Вы должны setMax (100) на progreso для проверки. Но в других отношениях хороший. Как он лучше, чем другие ответы. – Patrick Boos 16 December 2014 в 20:37

Я думаю, что пришел к выводу, что HyperTerminal не играет хорошо. Я запустил следующий тест:

  1. Запускают мой сервис в "консольном режиме", он начинает переключать устройство вкл\выкл (я могу сказать, он - светодиод).

  2. Запускают HyperTerminal и соединяются с портом. Устройство остается (HyperTerminal повышает DTR), Мой сервис пишет в журнал событий, что это не может открыть порт

  3. Остановка HyperTerminal, я проверяю, что это правильно закрывается с помощью диспетчера задач

  4. , устройство остается неизменным (HyperTerminal понизил DTR), мое приложение продолжает писать в журнал событий, говоря, что это не может открыть порт.

  5. я запускаю третье приложение (тот, который я должен сосуществовать с), и скажите ему соединяться с портом. Я делаю так. Никакие ошибки здесь.

  6. я останавливаю вышеупомянутое приложение.

  7. ВУАЛЯ, мой сервис умирает снова, порт открывается успешно, и светодиод идет ВКЛ\ВЫКЛ.

1
ответ дан Thomas Kjørnes 14 January 2009 в 01:19
поделиться
  • 1
    @EliKonky находил, что способ получить доступ к методу обратного вызова анимации обновить другое представление, applyTransformation() сохранил мой день! Благодарит тонну. – ritesht93 23 November 2016 в 05:52

Существует ли серьезное основание помешать Вашему сервису "владеть" портом? Посмотрите на встроенный сервис UPS - как только Вы говорите ему, что существует UPS, присоединенный к, скажем, COM1, можно поцеловать на прощание с тем портом. Я предложил бы, чтобы Вы сделали то же, если нет сильное операционное требование для совместного использования порта.

0
ответ дан Coderer 14 January 2009 в 01:19
поделиться

Этот ответ добирался до долго, чтобы быть комментарием...

я полагаю этому, когда Ваша программа находится в Потоке. Сон (1000) и Вы открываете свое Соединение HyperTerminal, HyperTerminal берет на себя управление над последовательным портом. Когда Ваша программа тогда просыпается и пытающийся открыть последовательный порт, IOException брошен.

Модернизация Ваш метод и попытка обработать открытие порта по-другому.

РЕДАКТИРОВАНИЕ: Об этом необходимо перезагрузить компьютер, когда программа перестала работать...

, Что, вероятно, потому что Ваша программа isnВґt действительно закрытый, откройте свой taskmanager и посмотрите, можно ли найти сервис программы. Обязательно остановите все Ваши потоки прежде, чем выйти из Вашего приложения.

0
ответ дан Anders R 14 January 2009 в 01:19
поделиться

Как сделать, надежный асинхронный comms

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

Использование APM с классом состояния сеанса, экземпляры которого управляют буферным и буферным курсором, совместно использованным через вызовы и реализацию обратного вызова, которая переносится EndRead в try...catch. В нормальном функционировании последняя вещь try, который должен сделать блок, настраивается следующий перекрытый обратный вызов ввода-вывода с вызовом к BeginRead().

то, Когда вещи спутываются, catch, должно асинхронно вызвать делегата в методе перезапуска. Реализация обратного вызова должна сразу выйти после catch блок так, чтобы логика перезапуска могла уничтожить текущую сессию (состояние сеанса почти наверняка повреждено) и создают новую сессию. Метод перезапуска должен не быть реализованным на классе состояния сеанса, потому что это препятствовало бы тому, чтобы он уничтожил и воссоздал сессию.

, Когда объект SerialPort закрывается (который произойдет, когда приложение выйдет) может быть незаконченная операция ввода-вывода. Когда это будет так, закрытие SerialPort инициирует обратный вызов, и при этих условиях EndRead выдаст исключение, которое неотличимо от общего comms shitfit. Необходимо установить флаг в состоянии сеанса для запрещения поведения перезапуска в catch блок. Это будет мешать Вашему методу перезапуска вмешаться в естественное завершение работы.

на Эту архитектуру можно положиться для не содержания на объект SerialPort неожиданно.

метод перезапуска справляется с закрытием и повторным открытием объекта последовательного порта. После вызова Close() на эти SerialPort объект звоните Thread.Sleep(5), чтобы дать ему шанс отпустить. Для чего-то еще возможно захватить порт, так быть готово иметь дело с этим при повторном открытии его.

2
ответ дан Peter Wone 14 January 2009 в 11:19
поделиться
  • 1
    @hamid_c да interpolatedTime является значением, переданным setDuration() – ritesht93 23 November 2016 в 15:50
Другие вопросы по тегам:

Похожие вопросы: