|
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
|
|
.NET 4.x Компонент SerialPort завешивает форму24.08.2016, 00:24. Показов 2867. Ответов 17
Метки нет (Все метки)
Доброй ночи!
Есть компонент SerialPort. На него пересылаю данные из внешнего устройства. Если в момент пересылки данных устройством попытаться закрыть порт - форма фризится намертво и с концами. Причем в Try - Catch ничего не приходит... Собственно в такой отлов ошибок у меня заключены все операции с компонентом порта да бы избежать "исключений". Каким образом закрыть порт так, чтобы в любом случае оно все закрыло и нигде не зависло? Спасибо.
0
|
|
| 24.08.2016, 00:24 | |
|
Ответы с готовыми решениями:
17
Скачивание через WebClient завешивает форму Компонент Serialport в VS C++ 2008 |
|
244 / 134 / 15
Регистрация: 26.12.2012
Сообщений: 267
|
|
| 24.08.2016, 13:57 | |
|
В данной ситуации при зависании в системе возникает ошибка которая пишется в протокол Windows (независимо от TryCatch программы). Хотелось бы узнать что там написанно?
0
|
|
|
79 / 72 / 4
Регистрация: 05.01.2016
Сообщений: 288
|
|
| 24.08.2016, 14:29 | |
|
0
|
|
|
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
|
|
| 07.10.2016, 00:44 [ТС] | |
|
Splinter_Cell, что это за протокол такой и где это все можно посмотреть?
Добавлено через 3 минуты 17Vasya17, был на этой странице триста раз... Там написано о методе .Close(). Им то я как раз и закрываю порт. Пишут что перед использованием .Open лучше подождать пока порт закроется... Но меня то это не касается... Пишут про исключения, но, как я и написал выше, туда ничего не приходит... Больше там ничего не написано.
0
|
|
|
244 / 134 / 15
Регистрация: 26.12.2012
Сообщений: 267
|
|
| 07.10.2016, 00:53 | |
|
0
|
|
|
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
|
|
| 07.10.2016, 05:43 | |
|
Stass48, Не закрывать порт, пока буфер передачи не будет пуст.
0
|
|
|
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
|
||||||
| 09.10.2016, 02:44 [ТС] | ||||||
|
Splinter_Cell, Может я чего-то не досмотрел, конечно, но все же в журнале пусто. Нет никаких событий на время зависания формы...
jkrnd, а подробнее? Я вот судя по Вашему совету сделал так (по теме строки 2 и 3):
![]() Если это не то, что Вы имели ввиду, то напишите пожалуйста подробнее, если можно с кодом... Вообще странно, что в Майкрософт хреново сделали эту процедуру закрытия порта. Погуглив по Интернету – проблема далеко не единичная. Но решения я так и не нашел... Добавлено через 5 минут Добавлю заранее, да бы исключить дальнейшее недопонимания: Кнопки открытия и закрытия порта у меня реализованы с защитой от повторных вхождений. То есть, нельзя нажать на закрытие порта пока сам порт не будет открыт и наоборот. Так же, нельзя открыть еще раз порт пока он открывается и точно так же с закрытием. Какие еще у кого будут мысли?
1
|
||||||
|
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
|
||||||
| 09.10.2016, 02:51 | ||||||
|
Stass48, На работу с Com-портом с помощью элемента управления угробил кучу времени и отказался от его использования. Его поведение в некоторых случаях непонятно, проще и надёжнее использовать класс SerialPort.
это нарыто в сети (не моё творчество). У меня проблем подобных Вашей не было.
1
|
||||||
|
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
|
|
| 09.10.2016, 04:07 | |
|
источник информации
1
|
|
|
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
|
||
| 17.10.2016, 13:57 [ТС] | ||
|
jkrnd, проверил все намного раньше, но написать могу только сейчас. В общем, дела такие.
Класс работает еще хуже, чем порт, видимо, компонент продуман получше класса (что и логично, так как используя класс, тебе дают больше возможности писать код самому). В моем случае проблема лежит скорее всего гораздо глубже. В своем устройстве, которое "общается" с компьютером, в качестве интерфейса-пеобразователя TTL/UART->USB я использую микросхему от Prolific. Точнее, китайский переходник на базе этой микросхемы. Сама же микросхема – китайская подделка и не работает с последними версиями официальных драйверов (так как в них уже ввели проверку подлинности чипа и этот чип ее, естественно, не проходит). Работает оно только когда ставишь драйвера постарее (где данной проверки еще нет). Но это драйвера еще времен Windows 7, как Вы понимаете с тех времен уже давно могли устранить все баги. К слову, даже когда я тупо выдергиваю USB, в диспетчере устройств ничего не пропадает, ком-порт так там и остается. Всунул еще раз и высунул – оп, пропал. Когда порт остается в системе при вытянутом устройстве, программа спокойно может его открывать и, по-моему, даже закрывать... Короче полный бред. Я вижу только два пути решения этой проблемы: 1) Очевидный. Идти в магазин и заказывать оригинальные чипы вплоть до FTDI, цены на которые, увы, не радуют и паять на базе них нормальный преобразователь. 2) А что если этот порт не закрывать вообще? Суть моей программы заключается просто в управлении компьютером с моего внешнего устройства и ведении логов всех действий. То есть эта программа будет помещена в автозагрузку и стартовать при запуске системы. Закрывать ее никто и никогда не будет (по идее). Закрываться она будет только при завершении работы винды. Но разве винда такая тупая что не закроет все порты сама перед выключением?) Короче, ребята, мне важно ваше, более опытное мнение по этому поводу. Активничайте, не стесняйтесь ![]() Добавлено через 54 минуты
1
|
||
|
|
||
| 17.10.2016, 16:05 | ||
|
Помимо Prolific, у FTDI большой выбор чипов. И есть ещё Silicon Labs CP210x. Можно взять чип от ST со встроенным USB, тогда никакой USB-UART мост вообще не понадобится.
2
|
||
|
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
|
|
| 18.10.2016, 20:38 [ТС] | |
|
Да уже понял что FTDI это самый "жирный" вариант хотя и недешевый. Но что поделать?
Да, у них большой выбор чипов и как я понял цена в основном зависит от скорости. Мне же нужно просто принять на комп несколько команд Uart (с ADC и прерывания по кнопке контроллера Atmega8A), то есть скорость тут как я думаю, мне не сильно важна. Поглядываю в строну FT232RL, но может быть есть что подешевле из этой линейки, которое мне подойдет? Если нет, возьму преобразователь на этой микре, благо на Космодроме пишут что у них преобразователи на оригинальных чипах... По поводу ST, я никогда не делал ничего на других чипах, кроме AVR, под них есть Bascom AVR на котором можно состряпать прошивочку. Уж сильно люблю VB ![]() Хотя данный язык имеет ряд недостатков (попробовать только дизассемблировать этот код, много лишнего ).
1
|
|
|
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
|
|
| 25.10.2016, 11:52 [ТС] | |
|
Итак, проблема решена!
Купил у себя рядышком в городе FDTI FT232RL, спаял на коленке преобразователь. Работает и ничего нигде не виснет! Хоть двадцать раз тыкай и во время пересылки данных! Судя по слухам в Интернете, с FTDI тоже есть проблемы в плане подделок. Но, судя по тому что у меня она завелась с официальными драйверами с сайта (драйвера если видят подделку – выводят ее со строя), то я купил именно оригиналки! Вывод: Китайцы – пи*орасы!
1
|
|
|
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
|
||||||||||||||||
| 23.01.2018, 02:18 [ТС] | ||||||||||||||||
|
UPDATE !!!
Как бы не так! Преобразователь здесь не причем, хотя все равно настоятельно рекомендую использовать только оригинальные чипы, а не китайский ширпотреб. Да, дорого, но это того стоит! Дело в БАГЕ класса SerialPort! Баг этот известен уже очень давно, с годов так 2007-х. Microsoft признала баг, но устранять его почему-то не захотела. Видимо, потому, что его можно обойти! Мне удалось найти два пути решения проблемы. Но о них позже. Сначала, давайте разберемся, почему форма зависает.
То есть, он ждет окончания операции ReadLine() Самое первое, что приходит в голову человеку при использовании класса или компонента (не важно) SerialPort, так это просто взять событие DataReceived и поместить в него инвок с выводом куда-то, например так:
Если мы в это время вызовем myPort.Close(), то мы завесим поток формы, а так как ReadLine() тоже будет ждать пока данные не запишутся в текстбокс, то вот он – ДЕДЛОК! Теперь о решениях. 1) Можно использовать вместо метода Invoke, метод BeginInvoke. В этом случае ReadLine() не будет дожидаться реакции от основного потока и спокойно сможет завершиться даже если основной поток формы будет приостановлен. Следовательно, зависания не произойдет. Однако, любые попытки работы ReadLine() асинхронно, работают как-то нестабильно. Где-то раз на 100 или даже 1000 чтений, читает либо две строки в одной, либо только часть строки, в общем, как я понял, лучше все таки синхронно (пробовал Producer-Consumer в реализации через BlockingCollection). Поэтому, метод 2. 2) Вызвать метод MyPort.Close() не из основного потока формы, а из постороннего. В таком случае метод Close() не будет блокировать поток формы и дедлока не произойдет. Вопрос лишь в том, как написать некоторую надстройку типа:
Уже неделю бьюсь, не могу осилить! Всё либо костыли, либо криво. В общем, мне не понравилось. Может кто другой осилит?
0
|
||||||||||||||||
|
|
|
| 23.01.2018, 08:12 | |
|
Stass48, просто не используйте ни ReadLine, ни DataReceived.
Чтение с последовательного порта без использования Sleep
1
|
|
|
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
|
|
| 24.01.2018, 13:18 [ТС] | |
Сообщение было отмечено OwenGlendower как решение
Решение
Rius, может быть в каких-то серьезных задачах Ваше решение и имеет право на существование, но, конкретно в моем случае, считаю, что это уж слишком заморочно и неоправданно сложно. Единственное, в чем я сомневаюсь (хотя наверное я ошибаюсь), так как событие DataReceived срабатывает по нескольку раз за строку, а ReadLine() стопорит выполнение до момента получение символа NewLine, то у нас может начать копиться очередь из событий DataReceived. Одновременно этой моей паранойе успокаивает мысль, что в момент, когда строка все таки получена, а новая передаваться еще не начала, то программа бегом успевает прогнать всю очередь. Так что скорее всего, она не должна накапливаться постоянно.
В крайнем случае, у ReadLine() есть возможность таймаута. Это чтобы уж совсем наверняка. Вместо Ваших методов, предлагаю свой вариант решения. Прикрепляю проект (кому надо, тот по аналогии сможет использовать этот код или написать класс). Дрюкал порт как мог кнопками открыть-закрыть одновременно передавая данные с FT232RL и в результате смог обнаружить только два вида порчи данных: 1) Когда приходит только концовка. Что не удивительно, ведь внешнее устройство уже начало передачу данных, а мы только открыли порт и начали принимать данные. Понятное дело, что мы сможем принять только то, что успеем. Пример: Передавали "Sample", получили "mple" или подобное. 2) Очень и очень редко, но получалось так, что соединяло часть первой строки с полностью второй строкой. Пример: "SampSample". Это я объяснить не смог. Но вроде бы после того как я ввел принудительную очистку буфера при открытии порта, этот глюк прекратился. Напомню, что все, что написано выше, происходит только при открытии и закрытии порта и одновременно этому – передачи данных. Поэтому: 1) Глюки вполне оправданы 2) Последствия глюков легко можно обрабатывать в функции, которая будет парсить принятые данные (такая функция будет присутствовать в 99% проектов, разве что кто-то будет писать свое приложение-терминал). После того как порт открыт, никаких глюков и артефактов при приеме данных замечено не было. Хотя от них никто не застрахован и все равно скорее всего вы будете на это рассчитывать в своем приложении, корректно обрабатывая подобные случаи в своем коде. По желанию можно ввести таймаут на получение строки (писал выше), так как микроконтроллер – не человек, он либо передает строку довольно быстро, либо значит что-то уже пошло не так и данные не принялись или не дошли. Мой проект демонстрирует пример того, как можно избежать случайного дедлока при закрытии последовательного порта. P. S.: Прошу модераторов отметить этот пост как "лучший ответ", так как он является одним из вариантов решения данной проблемы.
1
|
|
|
|
||
| 24.01.2018, 13:32 | ||
|
Через ваш вариант я проходил годы назад, в ходе отладки разнообразных способов. Но, как говорится, моё дело предложить, ваше - отказаться.
1
|
||
|
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
|
||
| 24.01.2018, 14:33 [ТС] | ||
![]() Но... Читайте внимательно. Первое – вообще не глюк! Как можно претендовать на данные, которые были переданы раньше, чем был открыт порт? Второе – сейчас существует скорее только у меня в голове, так как я сколько не пробовал, то не смог воспроизвести данный глюк повторно (после корректировки кода). Костыли будут в любом случае, так как исходную проблему "в корне", как Вы говорите, смогут решить только авторы класса. Наша задача – обойти проблему. Но сделать это нужно грамотно и как можно менее костыльно (полностью некостыльно и в то же время просто – не получится). У Вас ведь тоже те же костыли, согласитесь и это нормально, потому что выбора нам с Вами разработчики не оставили и нашего мнения не спросили ![]() Не забывайте, что речь идет о методе, который позволяет корректно принять ТОЛЬКО ЦЕЛУЮ СТРОКУ, а не каждый символ или бит по отдельности (как например, когда мы вводим данные с клавиатуры в терминале вручную или передаем файл по ком-порту)! Может быть, Ваши методы имеют возможность работать идеально во всех условиях, но какой смысл усложнять код ради получение возможности, которая никогда не будет использоваться (по крайней мере у меня)? Данные передаются и принимаются исправно, проверено! Все работает очень стабильно... По сути, мое решение заключается лишь в том, что буферизирует уже принятые строки с целью избежания дедлока по закрытию порта. И тема у меня имеет соответствующее название. Так что пусть будет) Я считаю, что для обмена строками Компьютер – Микроконтроллер, этого многим хватит за глаза. А проверку на ошибки приема данных придется делать по-любому, причем с обеих сторон. Мало ли, напряжение в сети скаконуло и полетел какой-то мусор... Огромное спасибо за Ваши труды, но такое усложнение, конкретно в моем случае будет просто не рациональным, неоправданно сложным, если быть точнее. Подведем итоги: В данной теме была представлена проблема случайного зависания приложения при выполнении метода SerialPort.Close(). Проблема была детально изучена, приведены причины и объяснения почему она возникает. Так же, приведены варианты решения данной проблемы, а так же, конкретные примеры готовой реализации. Каждое решение по-своему хорошо и не претендует на истинность, предоставляется "как есть".
0
|
||
| 24.01.2018, 14:33 | |
|
Помогаю со студенческими работами здесь
18
Приём данных через компонент serialport Можно ли взять с toolbox компонент serialport и внутри него написать значение com порта Serialport.write и serialport.basestream.write - в чем разница Компонент изменяющий форму Программно добавить на форму компонент Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога
Финальные проекты на Си и на C++:
hello-sdl3-c. zip
hello-sdl3-cpp. zip
Результат:
|
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога
MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
|
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд.
Даже если у вас. . .
|
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает
монорепозиторий в котором находятся все исходники.
При создании нового решения, мы просто добавляем нужные проекты
и имеем. . .
|
|
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение:
В этой книге («Подход, основанный на вариантах использования») Ивар утверждает,
что архитектура программного обеспечения — это
структуры,. . .
|
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога
Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
|
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога
Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip
На первой гифке отладочные линии отключены, а на второй включены:. . .
|
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога
Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем.
. . .
|