<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872585</guid>
        <pubDate>Mon, 25 Jul 2022 11:21:49 +0000</pubDate>
        <title>Проблема с TComPort / WaitForSingleObject</title>
        <link>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872585</link>
        <description><![CDATA[ЫукпШ: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=428742&view=findpost&p=3872084'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Виталь &#064; <time class="tag-quote__quoted-time" datetime="2022-07-21T02:20:17+03:00">20.07.22, 23:20</time></span><div class='quote '>Далее вызывается WaitForAsync, в ней WaitForSingleObject() возвращает результат как только получен ответ от устройства, GetOverlappedResult собственно считывает данные, ну и далее по тексту.</div></div><br>
Не совсем так.<br>
При инициализации порта указывается несколько тайм-аутов, в том числе на приём.<br>
Поэтому Wait... может завершиться совершенно законно с нулевым<br>
количеством принятых байт. И эту ситуацию надо отличать от штатной.<br>
Кроме того, могут быть приняты не все байты за один Wait.<br>
<div class='tag-quote'><span class='tag-quote-prefix'>Цитата</span> <div class='quote '><br>
 В ней на WaitForSingleObject с параметром INFINITE (именно бесконечность была в оригинальном коде) все благополучно наглухо зависает<br>
</div></div><br>
Может тайм-ауты не спрограммированы ?<br>
Как я подозреваю, смысл использования INFINITE (максимального ожидания) в этой wait - функции в том,<br>
чтобы реальный тайм-аут операции ожидания определялся заданными тайм-аутами COMM-порта.<br>
(Которые могут меняться от проекта к проекту.)<br>
---<br>
Возникающая исключительная ситуация говорит от том, что где-то серьёзная<br>
паталогия. При этом компонент TComPort может быть совершенно не виноват.<br>
---<br>
<strong class='tag-b'>Виталь</strong>, ты читаешь/пишешь данные из одного потока или из разных ?]]></description>
        <author>ЫукпШ</author>
        <category>Delphi: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872180</guid>
        <pubDate>Thu, 21 Jul 2022 15:20:41 +0000</pubDate>
        <title>Проблема с TComPort / WaitForSingleObject</title>
        <link>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872180</link>
        <description><![CDATA[Виталь: У меня короткие запросы и ответы, я не буду утверждать это со стопроцентной уверенностью, но возможно что пакетов больше 20 байт при управлении этим оборудованием не бывает. Если по какой-то причине в буфере накопятся ответы на несколько запросов - возможно. ОК, я учту Ваше замечание. К сожалению оказалось что компонент TComport далек от совершенства и его надо дорабатывать, хотя никогда раньше с подобными трудностями при работе с ним я не сталкивался.<br><br>В любом случае Вы сильно помогли. CancelIo в блоке except...end кажется решил проблему. Я вижу несколько Exception в логе по одному порту и одно в логе по второму за остаток вчерашнего вечера, ни одно из них не привело ни к зависанию, ни к постоянным ошибкам при отправке последующих команд  и исчезновению порта из системы, как было раньше. Это уже серьезный прогресс. Необходимо будет провести еще несколько экспериментов после исправлений кода и убедиться что ошибка в одной команде не приводит к каким-либо значимым сбоям при работе оборудования.]]></description>
        <author>Виталь</author>
        <category>Delphi: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872086</guid>
        <pubDate>Thu, 21 Jul 2022 00:01:27 +0000</pubDate>
        <title>Проблема с TComPort / WaitForSingleObject</title>
        <link>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872086</link>
        <description><![CDATA[macomics: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=428742&view=findpost&p=3872084'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Виталь &#064; <time class="tag-quote__quoted-time" datetime="2022-07-20T23:20:17+00:00">20.07.22, 23:20</time></span><div class='quote '>ReadAsync вызывает ReadFile с Overlapped, при этом в отличие от традиционного синхронного чтения из файла в буффер, в этот момент ничего не читается, BytesTrans возвращается 0, в Buffer^ ничего не пишется, и в моем случае Success всегда true (даже когда виснет).<br>
<br>
Далее вызывается WaitForAsync, в ней WaitForSingleObject() возвращает результат как только получен ответ от устройства, GetOverlappedResult собственно считывает данные, ну и далее по тексту.</div></div><br>
Все так. Только надо еще учесть, что у устройства есть свой внутренний буфер приема. И если в этом буфере уже достаточно байт, то ReadFile может вернуть True, а GetLastError = SUCCESS. Тогда из буфера устройства требуемое количество байт будет скопировано в буфер сразу и асинхронная операция не понадобится. Вот на этом и виснет. Ждет окончания асинхронной операции, которая даже не начиналась и система соответственно не собирается сигнализировать о ее окончании. Поэтому WaitForSingleObject(..., INFINITE) зависает.<br>
<br>
Но еще в операциях чтения/записи при возникновении ошибки хорошо было бы добавить CancelIo, чтобы не создавать бесконечных ожиданий на прием или передачу у драйвера устройства. Из-за этого и пропадает устройство. Его драйвер занят такой операцией в момент опроса дерева устройств (поэтому его даже не видно).]]></description>
        <author>macomics</author>
        <category>Delphi: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872084</guid>
        <pubDate>Wed, 20 Jul 2022 23:20:17 +0000</pubDate>
        <title>Проблема с TComPort / WaitForSingleObject</title>
        <link>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872084</link>
        <description><![CDATA[Виталь: Сложно. Схему работы я понимаю так:<br>
ReadAsync вызывает ReadFile с Overlapped, при этом в отличие от традиционного синхронного чтения из файла в буффер, в этот момент ничего не читается, BytesTrans возвращается 0, в Buffer^ ничего не пишется, и в моем случае Success всегда true (даже когда виснет). <br>
<br>
Далее вызывается WaitForAsync, в ней WaitForSingleObject() возвращает результат как только получен ответ от устройства, GetOverlappedResult собственно считывает данные, ну и далее по тексту.<br>
<br>
Если я вызову SetEvent где-то раньше WaitForSingleObject() - вызов WaitForSingleObject() вернется сразу, а GetOverlappedResult сразу вернет какую-то ошибку из-за чего появится Exception что я и увидел при прошлом эксперименте. Похожая ситуация если WaitForSingleObject 5 секунд возвращается с ошибкой таймаут.<br>
<br>
Оно то будет правильно, но блок if not Success then у меня никогда еще не выполнялся и GetLastError у меня всегда ERROR_IO_PENDING (не видел SUCCESS).<br>
<br>
CancelIO я закинул в Except...end. На удивление, пока не висло (но начинал с того что это процесс спонтанный, вообще счастье что ошибка происходила больше 2 раз за последний час. Очень сложно такие вещи дебажить.<br>
<br>
<div class='tag-quote'><span class='tag-quote-prefix'>Цитата</span> <div class='quote '>if GetLastError = ERROR_IO_PENDING then // Требуется ожидание завершения асинхронной операции<br>
            Result := WaitForAsync(AsyncPtr)<br>
        else Result := Success;</div></div><br>
вот это сейчас сделаю, это правильно, а то предыдущий вариант if Success &lt;&gt; 0 then все обваливал.]]></description>
        <author>Виталь</author>
        <category>Delphi: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872081</guid>
        <pubDate>Wed, 20 Jul 2022 22:36:49 +0000</pubDate>
        <title>Проблема с TComPort / WaitForSingleObject</title>
        <link>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872081</link>
        <description><![CDATA[macomics: При получении этой ошибки добавьте <a class='tag-url' href='https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-cancelio' target='_blank'>CancelIo(FHandle);</a><br>
Должно отменить ошибочную операцию в/в. Это должно оживлять COM порт без необходимости перезагрузки.<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp;if not Success then begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;CancelIo(FHandle);</div><div class="code_line">&nbsp;&nbsp; &nbsp;raise EComPortExt.Create(FPort, ErrorCode(AsyncPtr), GetLastError);</div><div class="code_line">&nbsp;&nbsp;end;</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp;function TCustomComPort.ReadAsync(var Buffer:TCPortBytes; Count: Integer; var AsyncPtr: PCPortAsync): Integer;</div><div class="code_line">&nbsp;&nbsp; &nbsp;var</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Success: Boolean;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;BytesTrans: DWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;lastErr:DWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;if AsyncPtr = nil then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;raise EComPort.Create(FPort,CError_InvalidAsync);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;AsyncPtr^.Kind := okRead;</div><div class="code_line">&nbsp;&nbsp; &nbsp; </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Buffer[0] := AnsiChar($FF);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;// Note the position of the caret (^). It compiles fine but doesn&#39;t work without &quot;Buffer^&quot;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Success := ReadFile(FHandle, Buffer^, Count, BytesTrans, @AsyncPtr^.Overlapped)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;or (GetLastError = ERROR_IO_PENDING);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Result := Count;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;if not Success then begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lastErr := GetLastError;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if lastErr = SUCCESS then begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SetEvent(FPort);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;exit;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end else begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;result := 0;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if FReadAsyncExceptionsEnabled then begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;raise EComPortExt.Create(FPort, CError_ReadFailed, lastErr);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end else begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Inc(FReadAsyncErrorCount);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;FReadAsyncLastError := lastErr;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;exit;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div></ol></div></div></div></div>Так будет правильнее. <br>
<br>
<span class="tag-color tag-color-named" data-value="mergepost" style="color: mergepost"><span class='tag-size' data-value='7' style='font-size:7pt;'>Добавлено <time class="tag-mergetime" datetime="2022-07-20T23:03:47+00:00">20.07.22, 23:03</time></span></span><br>
В общем как-то так должно сработать. Смысл в том, что при успешном начале чтения из COM или полностью считанном блоке из COM порта функция возвращает значение отличное от 0. Тогда должна быть задействована задержка. Хотя судя по всему при Success не стоит запускать задержку. Тогда стоит разделить значения переменной Result на 2. Флаг необходимости задержки и количество считанных байт. Еще можно проверять GetLastError = ERROR_IO_PENDING перед вызовом WaitForAsync.<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp;function TCustomComPort.Read(Buffer:TCPortBytes; Count: Integer): Integer;</div><div class="code_line">&nbsp;&nbsp; &nbsp;var</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;AsyncPtr: PCPortAsync;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Success: Integer;</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Result := 0;</div><div class="code_line">&nbsp;&nbsp; &nbsp;{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;OutputDebugString(&#39;TCustomComPort.Read &#39;+inttostr(Count)+&#39; bytes&#39;);</div><div class="code_line">&nbsp;&nbsp; &nbsp;{$endif}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;CportInitAsync(AsyncPtr);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;try</div><div class="code_line">&nbsp;&nbsp; &nbsp;{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;OutputDebugString(&#39;&#62;&#62; Before ReadAsync&#39;);</div><div class="code_line">&nbsp;&nbsp; &nbsp;{$endif}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Success := ReadAsync(Buffer, Count, AsyncPtr); // Сохраняем передаваемое количество байт</div><div class="code_line">&nbsp;&nbsp; &nbsp;{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;OutputDebugString(&#39;&#62;&#62; After ReadAsync&#39;);</div><div class="code_line">&nbsp;&nbsp; &nbsp;{$endif}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if GetLastError = ERROR_IO_PENDING then // Требуется ожидание завершения асинхронной операции</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Result := WaitForAsync(AsyncPtr)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;else Result := Success;</div><div class="code_line">&nbsp;&nbsp; &nbsp;{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;OutputDebugString(&#39;&#62;&#62; After WaitForAsync&#39;);</div><div class="code_line">&nbsp;&nbsp; &nbsp;{$endif}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;finally</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;CportDoneAsync(AsyncPtr);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div></ol></div></div></div></div>]]></description>
        <author>macomics</author>
        <category>Delphi: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872079</guid>
        <pubDate>Wed, 20 Jul 2022 22:30:58 +0000</pubDate>
        <title>Проблема с TComPort / WaitForSingleObject</title>
        <link>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872079</link>
        <description><![CDATA[Виталь: Спасибо что находите время отвечать среди ночи. Сейчас попробую SetEvent<br>
За это время обернул ReadAsync() и WaitForAsync() в общий try...except и на выходе получил<br>
<div class='tag-quote'><span class='tag-quote-prefix'>Цитата</span> <div class='quote '>Exception in Read: COM Port Error: Unknown Error #0 on COM3</div></div>Да, эта гадость сегодня слишком часто воспроизводится.<br>
<br>
Вот этот код 0 передается в параметре AWinCode в EComPortExt.Create()<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">inherited Create( &#39;COM Port Error: &#39;+ComErrorMessage(AWinCode)+&#39; on &#39;+port);</div></ol></div></div></div></div><br>
<br>
Но это очевидно лезет отсюда<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp;Success := (Signaled = WAIT_OBJECT_0) and</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;(GetOverlappedResult(FHandle, AsyncPtr^.Overlapped, BytesTrans, False));</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;if not Success then</div><div class="code_line">&nbsp;&nbsp; &nbsp;raise EComPortExt.Create(FPort, ErrorCode(AsyncPtr), GetLastError);</div></ol></div></div></div></div><br>
И толком мне ничего  не дает. Поскольку COM порт снова пропал из системы - перезагрузка, за это время допишу SetEvent. Почему порт пропадает я так и не понял, думал что как-то связано с тем что не вызывается CportDoneAsync(AsyncPtr), но не то.<br>
<br>
<br>
С SetEvent падает сразу, это в if Success then<br>
<div class='tag-quote'><span class='tag-quote-prefix'>Цитата</span> <div class='quote '>22:32:53 TCustomComPort.Read 5 bytes<br>
22:32:53 TCustomComPort.ReadAsync 0 bytes Success<br>
22:32:53 TCustomComPort.WaitForAsync WaitForSingleObject 000004D0<br>
22:32:53 TCustomComPort.WaitForAsync Signaled=0<br>
22:32:53 &gt;&gt; Exception in Read: COM Port Error: Unknown Error #996 on COM16<br>
(ERROR_IO_INCOMPLETE, Overlapped I/O event is not in a signaled state.)</div></div>]]></description>
        <author>Виталь</author>
        <category>Delphi: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872073</guid>
        <pubDate>Wed, 20 Jul 2022 22:13:01 +0000</pubDate>
        <title>Проблема с TComPort / WaitForSingleObject</title>
        <link>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872073</link>
        <description><![CDATA[macomics: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=428742&view=findpost&p=3872071'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Виталь &#064; <time class="tag-quote__quoted-time" datetime="2022-07-20T21:58:08+00:00">20.07.22, 21:58</time></span><div class='quote '>Удалось воспроизвести ошибку, приводившую к зависанию пока в предыдущем варианте кода, но с логом GetLastError и результата Success.</div></div><br>
При получении Success можете просто вызвать <div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">SetEvent(AsyncPtr^.Overlapped.hEvent);</div></ol></div></div></div></div> Тогда <div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">Signaled := WaitForSingleObject(AsyncPtr^.Overlapped.hEvent, INFINITE);</div></ol></div></div></div></div>не должна зависнуть. Проблема в том, что ReadFile закончила работу нормально (без необходимости ожидания).<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=428742&view=findpost&p=3872071'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Виталь &#064; <time class="tag-quote__quoted-time" datetime="2022-07-20T21:58:08+00:00">20.07.22, 21:58</time></span><div class='quote '>Может ли подобная ситуация произойти если контроллер не ответил на запрос, на который согласно документации должен был ответить?</div></div><br>
Может.<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=428742&view=findpost&p=3872071'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Виталь &#064; <time class="tag-quote__quoted-time" datetime="2022-07-20T21:58:08+00:00">20.07.22, 21:58</time></span><div class='quote '>Или тогда вернется 0 байт и зависаний быть не должно?</div></div><br>
Нет. По вашему алгоритму вы до посинения (или в течении 5 сек) ждете передачи от контроллера.<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=428742&view=findpost&p=3872071'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Виталь &#064; <time class="tag-quote__quoted-time" datetime="2022-07-20T21:58:08+00:00">20.07.22, 21:58</time></span><div class='quote '>Вообще в компоненте TComPort таймауты установлены, 2 секунды или что-то около того, потому если кабели не подключены программа ошибку выводит, а не зависает. </div></div><br>
Это другие таймауты. В вашей функции таймаут - ждать до посинения (INFINITE) был в оригинале.]]></description>
        <author>macomics</author>
        <category>Delphi: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872071</guid>
        <pubDate>Wed, 20 Jul 2022 21:58:08 +0000</pubDate>
        <title>Проблема с TComPort / WaitForSingleObject</title>
        <link>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872071</link>
        <description><![CDATA[Виталь: Вариант с вызовом WaitForAsync только если в ReadAsync не было ошибок пока не сработал, при инициализации первые несколько команд прошли, следующая крешанула программу. Буду разбираться днем в чем отличие.<br>
<br>
Удалось воспроизвести ошибку, приводившую к зависанию пока в предыдущем варианте кода, но с логом GetLastError и результата Success.<br>
Как ни странно, <div class='tag-quote'><span class='tag-quote-prefix'>Цитата</span> <div class='quote '>TCustomComPort.ReadAsync 0 bytes Success, lastErr = 997</div></div><br>
То есть BytesTrans равен 0, в MSDN написано<br>
<div class='tag-quote'><span class='tag-quote-prefix'>Цитата</span> <div class='quote '>ReadFile sets this value to zero before doing any work or error checking. Use NULL for this parameter if this is an asynchronous operation to avoid potentially erroneous results.</div></div>То есть ноль это законно для lpOverlapped &lt;&gt; nil, причем написано даже что этот параметр тоже должен быть nil. А 997 это ERROR_IO_PENDING. То есть в ReadAsync все выполняется как задумано, какого ж тогда лешего происходит таймаут в WaitForSingleObject...<br>
<br>
<br>
Уточню. Программа шлет контроллеру пакет-запрос и получает пакет-ответ. Может ли подобная ситуация произойти если контроллер не ответил на запрос, на который согласно документации должен был ответить? Или тогда вернется 0 байт и зависаний быть не должно? Вообще в компоненте TComPort таймауты установлены, 2 секунды или что-то около того, потому если кабели не подключены программа ошибку выводит, а не зависает.]]></description>
        <author>Виталь</author>
        <category>Delphi: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872059</guid>
        <pubDate>Wed, 20 Jul 2022 19:33:30 +0000</pubDate>
        <title>Проблема с TComPort / WaitForSingleObject</title>
        <link>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872059</link>
        <description><![CDATA[macomics: Не совсем. При возникновении ошибки hEvent не устанавливается в состояние Signaled и система его не установит тоже никогда. Отсюда и будет зависание.<br>
Т.е. При Success = False либо надо вручную вызвать SetEvent или не вызывать функцию <div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">Result := WaitForAsync(AsyncPtr);</div></ol></div></div></div></div> если предыдущий вызов <div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">ReadAsync(Buffer, Count, AsyncPtr);</div></ol></div></div></div></div> вернет not Success.<br>
Логика должна быть такая. Но тут вызывается функция ожидания даже если при чтении из Com-порта произошла ошибка.<br>
<br>
Прочитайте про работу hEvent в структуре <a class='tag-url' href='https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-overlapped' target='_blank'>Overlapped</a> <br>
<br>
<span class="tag-color tag-color-named" data-value="mergepost" style="color: mergepost"><span class='tag-size' data-value='7' style='font-size:7pt;'>Добавлено <time class="tag-mergetime" datetime="2022-07-20T19:42:48+00:00">20.07.22, 19:42</time></span></span><br>
т.е. код стоит изменить на такой<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">function TCustomComPort.Read(Buffer:TCPortBytes; Count: Integer): Integer;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;AsyncPtr: PCPortAsync;</div><div class="code_line">&nbsp;&nbsp;Success: Integer;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;Result := 0;</div><div class="code_line">{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp;OutputDebugString(&#39;TCustomComPort.Read &#39;+inttostr(Count)+&#39; bytes&#39;);</div><div class="code_line">{$endif}</div><div class="code_line">&nbsp;&nbsp;CportInitAsync(AsyncPtr);</div><div class="code_line">&nbsp;&nbsp;try</div><div class="code_line">{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp;OutputDebugString(&#39;&#62;&#62; Before ReadAsync&#39;);</div><div class="code_line">{$endif}</div><div class="code_line">&nbsp;&nbsp; &nbsp;Success := ReadAsync(Buffer, Count, AsyncPtr); // Сохраняем передаваемое количество байт</div><div class="code_line">{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp;OutputDebugString(&#39;&#62;&#62; After ReadAsync&#39;);</div><div class="code_line">{$endif}</div><div class="code_line">&nbsp;&nbsp; &nbsp;if Success &#60;&#62; 0 then // Передаваемое количество байт не равно 0, тогда ожидаем завершения передачи</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Result := WaitForAsync(AsyncPtr);</div><div class="code_line">{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp;OutputDebugString(&#39;&#62;&#62; After WaitForAsync&#39;);</div><div class="code_line">{$endif}</div><div class="code_line">&nbsp;&nbsp;finally</div><div class="code_line">&nbsp;&nbsp; &nbsp;CportDoneAsync(AsyncPtr);</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">end;</div></ol></div></div></div></div>и соответственно<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">function TCustomComPort.ReadAsync(var Buffer:TCPortBytes; Count: Integer; var AsyncPtr: PCPortAsync): Integer;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;Success: Boolean;</div><div class="code_line">&nbsp;&nbsp;BytesTrans: DWORD;</div><div class="code_line">&nbsp;&nbsp;lastErr:DWORD;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;if AsyncPtr = nil then</div><div class="code_line">&nbsp;&nbsp; &nbsp;raise EComPort.Create(FPort,CError_InvalidAsync);</div><div class="code_line">&nbsp;&nbsp;AsyncPtr^.Kind := okRead;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;Buffer[0] := AnsiChar($FF);</div><div class="code_line">&nbsp;&nbsp;// Note the position of the caret (^). It compiles fine but doesn&#39;t work without &quot;Buffer^&quot;</div><div class="code_line">&nbsp;&nbsp;Success := ReadFile(FHandle, Buffer^, Count, BytesTrans, @AsyncPtr^.Overlapped)</div><div class="code_line">&nbsp;&nbsp; &nbsp;or (GetLastError = ERROR_IO_PENDING);</div><div class="code_line">&nbsp;&nbsp;if BytesTrans = 0 then BytesTrans := Count; // Если не будет ошибок возвращаем Count;</div><div class="code_line">&nbsp;&nbsp;if not Success then begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;BytesTrans := 0; // При ошибке возвращаем 0!</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;lastErr := GetLastError;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;if FReadAsyncExceptionsEnabled then begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;raise EComPortExt.Create(FPort, CError_ReadFailed, lastErr);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;end else begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Inc(FReadAsyncErrorCount);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;FReadAsyncLastError := lastErr;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;result := 0;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;exit;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;Result := BytesTrans;</div><div class="code_line">end;</div></ol></div></div></div></div>А INFINITE можете вернуть обратно.]]></description>
        <author>macomics</author>
        <category>Delphi: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872058</guid>
        <pubDate>Wed, 20 Jul 2022 19:18:35 +0000</pubDate>
        <title>Проблема с TComPort / WaitForSingleObject</title>
        <link>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872058</link>
        <description><![CDATA[Виталь: Ок, в Read() вызывается ReadAsync()<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// perform asynchronous read operation</div><div class="code_line">function TCustomComPort.ReadAsync(var Buffer:TCPortBytes; Count: Integer; var AsyncPtr: PCPortAsync): Integer;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;Success: Boolean;</div><div class="code_line">&nbsp;&nbsp;BytesTrans: DWORD;</div><div class="code_line">&nbsp;&nbsp;lastErr:DWORD;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;if AsyncPtr = nil then</div><div class="code_line">&nbsp;&nbsp; &nbsp;raise EComPort.Create(FPort,CError_InvalidAsync);</div><div class="code_line">&nbsp;&nbsp;AsyncPtr^.Kind := okRead;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;Buffer[0] := AnsiChar($FF);</div><div class="code_line">&nbsp;&nbsp;// Note the position of the caret (^). It compiles fine but doesn&#39;t work without &quot;Buffer^&quot;</div><div class="code_line">&nbsp;&nbsp;Success := ReadFile(FHandle, Buffer^, Count, BytesTrans, @AsyncPtr^.Overlapped)</div><div class="code_line">&nbsp;&nbsp; &nbsp;or (GetLastError = ERROR_IO_PENDING);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;if not Success then begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;lastErr := GetLastError;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;if FReadAsyncExceptionsEnabled then begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;raise EComPortExt.Create(FPort, CError_ReadFailed, lastErr);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;end else begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Inc(FReadAsyncErrorCount);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;FReadAsyncLastError := lastErr;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;result := 0;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;exit;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;Result := BytesTrans;</div><div class="code_line">end;</div></ol></div></div></div></div><br>
<br>
То есть если здесь not Success то следует анализировать GetLastError, я Вас правильно понял?<br>
Если внутри ReadAsync происходит ошибка (и функция возвращает 0) то какие мои дальнейшие действия - в коде не должна вызываться функция WaitForAsync(), в которой было бесконечное ожидание?]]></description>
        <author>Виталь</author>
        <category>Delphi: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872050</guid>
        <pubDate>Wed, 20 Jul 2022 18:19:44 +0000</pubDate>
        <title>Проблема с TComPort / WaitForSingleObject</title>
        <link>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872050</link>
        <description><![CDATA[macomics: Найдите где вызывается функция ReadFile/WriteFile(hComPort,...,Overlapped) - там будет callback функция, которую система вызывает по окончании чтения/записи в порт. Эта функция должна установить состояние hEvent по окончании данных в буфере, на котором зависает WaitForSingleObject.<br>Далее стоит искать там (в callback функции) причину зависания. Скорее всего эта функция будет вызываться из ReadAsync.]]></description>
        <author>macomics</author>
        <category>Delphi: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872048</guid>
        <pubDate>Wed, 20 Jul 2022 18:09:43 +0000</pubDate>
        <title>Проблема с TComPort / WaitForSingleObject</title>
        <link>https://forum.sources.ru/index.php?showtopic=428742&amp;view=findpost&amp;p=3872048</link>
        <description><![CDATA[Виталь: Доброго времени суток&#33;<br>
<br>
Я достаточно много лет использую компонент <a class='tag-url' href='https://sourceforge.net/projects/comport/' target='_blank'>TComPort</a> by Dejan Crnila. Баловался с факс-модемами, мобилками, было несколько серьезных разработок. Никаких проблем не возникало. И вот однажды стали возникать проблемы, проявляющиеся в виде зависания наглухо программы, управляющей механическим оборудованием.<br>
<br>
Не буду вдаваться в подробности, все команды сводятся к вызову <strong class='tag-b'>ComPort.Write()</strong> и последующему <strong class='tag-b'>ComPort.Read()</strong>. Пакеты данных формируются особым образом, проверяется контрольная сумма, железо не глючная ну и так далее.<br>
<br>
Максимальный режим дебага ничего не показал, пришлось залазить в исходники компонента и модифицировав задуманные разработчиками возможности CALLTRACE (модифицировал OutputDebugString) получил следующие выводы:<br>
<br>
TCustomComPort.Read у меня в следующем виде:<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// perform synchronous read operation</div><div class="code_line">function TCustomComPort.Read(Buffer:TCPortBytes; Count: Integer): Integer;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;AsyncPtr: PCPortAsync;</div><div class="code_line">begin</div><div class="code_line">{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp;OutputDebugString(&#39;TCustomComPort.Read &#39;+inttostr(Count)+&#39; bytes&#39;);</div><div class="code_line">{$endif}</div><div class="code_line">&nbsp;&nbsp;CportInitAsync(AsyncPtr);</div><div class="code_line">&nbsp;&nbsp;try</div><div class="code_line">{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp;OutputDebugString(&#39;&#62;&#62; Before ReadAsync&#39;);</div><div class="code_line">{$endif}</div><div class="code_line">&nbsp;&nbsp; &nbsp;ReadAsync(Buffer, Count, AsyncPtr);</div><div class="code_line">{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp;OutputDebugString(&#39;&#62;&#62; After ReadAsync&#39;);</div><div class="code_line">{$endif}</div><div class="code_line">&nbsp;&nbsp; &nbsp;Result := WaitForAsync(AsyncPtr);</div><div class="code_line">{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp;OutputDebugString(&#39;&#62;&#62; After WaitForAsync&#39;);</div><div class="code_line">{$endif}</div><div class="code_line">&nbsp;&nbsp;finally</div><div class="code_line">&nbsp;&nbsp; &nbsp;CportDoneAsync(AsyncPtr);</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">end;</div></ol></div></div></div></div><br>
<br>
Из нее вызывается функция<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// wait for asynchronous operation to end</div><div class="code_line">function TCustomComPort.WaitForAsync(var AsyncPtr: PCPortAsync): Integer;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;BytesTrans, Signaled: DWORD;</div><div class="code_line">&nbsp;&nbsp;Success: Boolean;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;if AsyncPtr = nil then</div><div class="code_line">&nbsp;&nbsp; &nbsp;raise EComPort.Create(FPort,CError_InvalidAsync);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp; OutputDebugString(PChar(&#39;TCustomComPort.WaitForAsync WaitForSingleObject! &#39;+ &nbsp; &nbsp; &nbsp;IntToHex(Integer(AsyncPtr^.Overlapped.hEvent),8)) );</div><div class="code_line">&nbsp;&nbsp;{$endif}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;//Signaled := WaitForSingleObject(AsyncPtr^.Overlapped.hEvent, INFINITE); //ORIGINAL</div><div class="code_line">&nbsp;&nbsp;Signaled := WaitForSingleObject(AsyncPtr^.Overlapped.hEvent, 5000);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp; OutputDebugString( PChar(&#39;TCustomComPort.WaitForAsync Signaled=&#39;+IntToStr(Signaled)) );</div><div class="code_line">&nbsp;&nbsp;{$endif}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;Success := (Signaled = WAIT_OBJECT_0) and</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;(GetOverlappedResult(FHandle, AsyncPtr^.Overlapped, BytesTrans, False));</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;if not Success then</div><div class="code_line">&nbsp;&nbsp; &nbsp;raise EComPortExt.Create(FPort, ErrorCode(AsyncPtr), GetLastError);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;if not FInputCountNotSupported then begin</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (AsyncPtr^.Kind = okRead) and (InputCount = 0) then begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp; &nbsp; OutputDebugString(&#39;TCustomComPort.WaitForAsync SendSignalToLink&#39;);</div><div class="code_line">&nbsp;&nbsp; &nbsp;{$endif}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;SendSignalToLink(leRx, False)</div><div class="code_line">&nbsp;&nbsp; &nbsp;end else</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;if AsyncPtr^.Data &#60;&#62; nil then begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; OutputDebugString(&#39;TCustomComPort.WaitForAsync TxNotifyLink&#39;);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{$endif}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;TxNotifyLink( TCPortBytes( AsyncPtr^.Data), AsyncPtr^.Size);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;{$ifdef CPORT_CALLTRACE}</div><div class="code_line">&nbsp;&nbsp; OutputDebugString( PChar(&#39;TCustomComPort.WaitForAsync BytesTrans=&#39;+IntToStr(BytesTrans)) );</div><div class="code_line">&nbsp;&nbsp;{$endif}</div><div class="code_line">&nbsp;&nbsp;Result := BytesTrans;</div><div class="code_line">end;</div></ol></div></div></div></div><br>
<br>
В ней на <strong class='tag-b'>WaitForSingleObject</strong> с параметром <strong class='tag-b'>INFINITE</strong> (именно бесконечность была в оригинальном коде) все благополучно наглухо зависает (основной поток программы со всеми вытекающими) при этом какие-то фоновые потоки, не связанные с портами, продолжают работать.<br>
Я изменил время ожидания на 5 секунд. Существенно лучше не стало. Программа перестала зависать, но все последующие попытки чтения из порта заканчивались исключением. Это позволило только добавить код, позволяющий вызвать оператора для перезагрузки. Нет, не программы, компьютера, так как даже после выхода порт остается недоступен в операционной системе (консольная команда mode не отображает его в списке).<br>
<br>
Вот CALLTRACE для успешного запроса / ответа с моими комментариями<br>
<div class='tag-quote'><span class='tag-quote-prefix'>Цитата</span> <div class='quote '>12:23:14 TCustomComPort.WaitForAsync WaitForSingleObject&#33; 000004C8<br>
12:23:14 TCustomComPort.WaitForAsync Signaled=0<br>
12:23:14 TCustomComPort.WaitForAsync TxNotifyLink<br>
12:23:14 TCustomComPort.WaitForAsync BytesTrans=5 //в порт ушло 5 байт данных<br>
12:23:14 TCustomComPort.DoneAsync<br>
12:23:14 TCustomComPort.Read 7 bytes //прочитать из порта 7 байт<br>
12:23:14 &gt;&gt; Before ReadAsync<br>
12:23:14 &gt;&gt; After ReadAsync<br>
12:23:14 TCustomComPort.WaitForAsync WaitForSingleObject&#33; 000004C8<br>
12:23:14 TCustomComPort.WaitForAsync Signaled=0<br>
12:23:14 TCustomComPort.WaitForAsync SendSignalToLink<br>
12:23:14 TCustomComPort.WaitForAsync BytesTrans=7<br>
12:23:14 &gt;&gt; After WaitForAsync //прочитано 7 байт успешно</div></div><br>
Вот проблемный запрос:<br>
<div class='tag-quote'><span class='tag-quote-prefix'>Цитата</span> <div class='quote '>12:23:14 TCustomComPort.WaitForAsync WaitForSingleObject&#33; 000004C8<br>
12:23:14 TCustomComPort.WaitForAsync Signaled=0<br>
12:23:14 TCustomComPort.WaitForAsync TxNotifyLink<br>
12:23:14 TCustomComPort.WaitForAsync BytesTrans=11 //в порт пошли 11 байт<br>
12:23:14 TCustomComPort.DoneAsync<br>
12:23:14 TCustomComPort.Read 3 bytes / TCustomComPort.Read //прочитать ответ 4 байта<br>
12:23:14 &gt;&gt; Before ReadAsync<br>
12:23:14 &gt;&gt; After ReadAsync<br>
12:23:14 TCustomComPort.WaitForAsync WaitForSingleObject&#33; 000004C8 //ожидаем<br>
//тут мы 5 секунд висим<br>
12:23:19 TCustomComPort.WaitForAsync Signaled=258 //<strong class='tag-b'>код ТАЙМАУТ</strong></div></div><br>
Вот как выглядят все последующие команды:<br>
<div class='tag-quote'><span class='tag-quote-prefix'>Цитата</span> <div class='quote '>12:23:19 TCustomComPort.WaitForAsync WaitForSingleObject&#33; 000004C8<br>
12:23:19 TCustomComPort.WaitForAsync Signaled=0<br>
12:23:19 TCustomComPort.WaitForAsync TxNotifyLink<br>
12:23:19 TCustomComPort.WaitForAsync BytesTrans=5 //ушло 5 байт<br>
12:23:19 TCustomComPort.DoneAsync<br>
12:23:19 TCustomComPort.Read 7 bytes //прочитать 7 байт<br>
12:23:19 &gt;&gt; Before ReadAsync<br>
12:23:19 &gt;&gt; After ReadAsync<br>
12:23:19 TCustomComPort.WaitForAsync WaitForSingleObject&#33; 000004C8 //ожидаем<br>
12:23:19 TCustomComPort.WaitForAsync Signaled=0 //<strong class='tag-b'>сразу возврат с кодом 0</strong><br>
после чего где-то в коде компонента возникает исключение, которое мой код отрабатывает как ошибку<br>
</div></div><br>
<br>
Ну и вопросы - кто виноват и что делать?<br>
<br>
Дело не в длине пакета данных, так как в порт постоянно отправляются команды 5, 11 байт и другой длины.<br>
<br>
Возможно, это поведение операционной системы либо внешнего USB-RS232 адаптера (девайс качественный, не один год используется).<br>
<br>
А может это как-то связано с поведением контроллера, с которым ведется коммуникация (но после перезагрузки ПК и запуска программы заново контроллер отвечает нормально, перезагрузка по питанию не производится).<br>
<br>
Еще один момент который может влиять на вероятность возникновения проблемы (несколько раз в сутки при интенсивном использовании) это то что управление на самом деле производится двумя однотипными устройствами через однотипные контроллеры (разные только номера COM портов) и непосредственно перед зависанием <strong class='tag-b'>в один и тот же контроллер уходит подряд 7 команд серией</strong> (7я - зависающая), хотя обычное поведение это одна команда в один порт, за ней тут же одна в другой порт или серии по несколько команд в каждый порт попеременно. Возможно что серия 7 команд в один порт (записать, прочитать) самая длинная во всем коде программы.<br>
<br>
Кроме того, длина кабеля до проблемного контроллера примерно в 2 раза больше по прямой (но в пределах допустимого) в то время как кабель до другого устройства имеет незначительно меньшую длину и свернут в колечко рядышком с тороидальным трансформатором. Да, я знаю что так нельзя, но пока это никому не мешало, как раз с этим устройством проблем нет. Но так уж сложилось что серия из 7 команд подряд в контроллер, в процессе работы с которым возникает проблема, посылается намного чаще, чем в другой контроллер, потому сказать зависал бы второй - не могу. Поменять их местами тоже не представляется возможным.<br>
<br>
Понимаю что проблема достаточно сложная, потому прошу гуру форума подсказать что касается работы TComPort с портом и вызовом WaitForSingleObject - почему может быть такое поведение?]]></description>
        <author>Виталь</author>
        <category>Delphi: Общие вопросы</category>
      </item>
	
      </channel>
      </rss>
	