2015-09-14 4 views
2

Я работаю над проектом, где я общаюсь с другим устройством через COM-порт. Для входящих данных я использую событие VaComm1RXchar, там я храню сообщение в массиве и увеличиваю msgIndex, который представляет количество сообщений.Что происходит, когда вызывается ShowMessage?

Затем я вызываю функцию, где я работаю с этим сообщением.

Внутри этой функции этот тайм-аут цикла, где я жду этого сообщения:

while MsgIndex < 1 do 
    begin 
    stop := GetTickCount; 
    if (stop - start)> timeout then 
    begin 

     MessageBox(0, 'Timeout komunikace !', 'Komunikace', MB_OK); 
     exit(false); 
    end; 
    sleep(10); 
    end; 

Странная вещь для меня является то, что, когда есть это, как это выше, то это всегда заканчивается тайм-аут. Но когда я встал перед этим во время цикла ShowMessage («Ожидание»), то он работает корректно.

Кто-нибудь знает, что может вызвать это и как я могу его решить? Заранее спасибо!

ответ

6

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

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

Вы можете быть уверены, что это в случае, если это работает (пожалуйста, никогда не писать код, как это - это просто, чтобы доказать точку):

while MsgIndex < 1 do begin 
    stop := GetTickCount; 
    if (stop - start)> timeout then begin  
    MessageBox(0, 'Timeout komunikace !', 'Komunikace', MB_OK); 
    exit(false); 
    end; 
    Application.ProcessMessages; // service the message queue so that 
    sleep(10);     // your Rx event can be handled 
end; 

Если есть урок здесь в том, что RS- 232 действительно нужно делать на фоновом потоке. Большинство реализаций событий "some chars have been received" приводят к ужасному коду по той причине, что вы открываете. Ваш основной поток должен быть свободен для обработки сообщения о том, что символы были получены, но в то же время у вас должен быть параллельный процесс, ожидающий, что эти принятые символы завершат четкую инструкцию. В управляемой событиями не существует разумного решения для управления интерфейсом и порта связи одновременно в одном потоке.

Набор компонентов, таких как AsyncPro **, например, переносит эту функциональность в пакеты данных, в которых используются синхронные события, но где компоненты управляют обнаружением начала и конца строки (или байтов) для рабочего потока. Это удаляет один уровень опроса из основного потока (т. Е. Вы всегда получаете событие, когда полный пакет данных прибыл, а не частичный). Кроме того, вы можете переместить работу связи в пользовательский поток и управлять этим самостоятельно.

В любом случае это лишь частично решение, конечно, поскольку вы по-прежнему не можете писать длинные процедурные методы в синхронных обработчиках событий, которые требуют ожидания com-трафика.Второй уровень опроса, который управляет последовательностью полных инструкций, по-прежнему будет нуждаться в том, чтобы перекачать очередь сообщений, если ваша одна процедура должна реагировать на последовательность более чем одной команды comport. То, о чем вам нужно подумать, - это разбить ваши длинные методы на более короткие куски, каждый в ответ на конкретные сообщения устройства.

В качестве альтернативы, для интенсивной процедурной автоматизации процесса также часто рекомендуется перемещать эту работу в фоновый поток. Таким образом, ваши рабочие потоки могут блокировать объекты синхронизации (или опросы в циклах занятости для обновлений состояния), пока они ждут событий с аппаратного обеспечения. Один поток может управлять трафиком с низким уровнем трафика, анализировать и ретранслировать эти команды или пакеты данных, тогда как второй поток может управлять процессом более высокого уровня, который обрабатывает последовательность полных команд comport, которые составляют ваш более крупный процесс. Основной поток должен в первую очередь отвечать только за сбор данных этих сообщений между рабочими, а не на то, чтобы самому ждать.

Смотрите также: I do not understand what Application.ProcessMessages in Delphi is doing


** VAComm может также поддерживать что-то вроде этого, я не знаю. API и документация не доступны для TMS для ASync32, поэтому вам необходимо проконсультироваться с вашей местной документацией.

0

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

Таким образом, решение для вас - это обслуживание очереди сообщений. Вызов Application.ProcessMessages в вашем цикле сделает это, но также создает другие проблемы. Подобно тому, как ваш пользовательский интерфейс становится повторным участником.

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

+0

Что касается голосования, я допустил ошибку здесь, что могу исправить? –

+1

+1 от меня ... это правильно, по существу, и ответы на уровне, соразмерном с вопросом. Похоже на голосование. –

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