Уважаемые форумчане, всем добрый день! Подскажите путь решения. Ситуация следующая. Пишу приложение на delphi7, которое через ком порт общается с устройствами в сети (до 255 устройств может быть). Пользуюсь компонентом-библиотекой для работы с ком-портом ComPort Library 4.10 от Dejan Crnila. Приложение сначала сделал однопоточное, ибо программка большую часть времени простаивает и ждет пакет, приходящий в ком порт от любого из устройств. События прихода данных в ком порт отслеживаются и обрабатываются процедурой onRxChar, которая является частью класса этой самой библиотеки. В этой процедуре-обработчике выполняется вся обработка поступивших пакетов, вся реакция на них. Все бы было хорошо, если бы не 2 нюанса.
1. Иногда из сети от устройства может прийти пакет, который должен "усыпить" программу на определенное время. Усыпление я делаю с помощью вызова модального окна без кнопки закрыть его, а только с предупреждением о том, что программа временно приостановлена. (Такой способ приемлем или можно как-то более красиво?):
Код:
procedure TF_Main.ComPort1RxChar(Sender: TObject; Count: Integer);
begin
ComPort1.Read(P_vhod,15);
If (P_vhod[9]=1) and (P_vhod[10]=2) and (P_vhod[12]=20)//Если пришел пакет на "засыпание" программы
then
begin
FWait:= TFWait.Create(Self);
FWait.ShowModal;
end;
if (P_vhod[9]=1) and (P_vhod[10]=2) and (P_vhod[12]=21)//Программе надо проснуться
then
FWait.Close;
...
еще много других реакций
...
Но когда запущено модальное окно, управление не переходит на прием следующего пакета, который выведет программу
из спящего состояния, а все выполнение останавливается на строчке FWait.ShowModal. Типа программа зависла.
2.В программе есть кнопка опроса устройств и отправки данных на устройства. В обработчике кнопки "опросить" запускается цикл от 1 до 255 каждые 50 мс по 3 раза на каждое устройство (765 итераций). Цикл длится примерно 40 секунд. В цикле я отправил пакет на устройство 1. Оно ответило пакетом. Этот пакет пришел в порт, НО обработчик ComPort1RxChar НЕ может пока сработать, ибо сейчас выполняется обработчик нажатия кнопки и выполняется цикл. Первое устройство ответило, мы не обработали пакет, второе ответило, мы не обработали....Я так понимаю, пока размера буфера хватает, эти байты там сохраняются. После окончания цикла мы, может быть, сможем обработать первые 10-15 пакетов с первых 10-15 устройств. И пропустим почти все пришедшие пакеты с остальных устройств. А если еще вдруг в процессе опроса придет пакет на засыпание программы. Мы его тоже можем не отловить получается. Я решил по нажатии кнопки "опросить" запустить дополнительный поток, слушающий ком порт:
Код:
procedure TF_Main.Btn_SchitSoStellyClick(Sender: TObject);
var
i,t:integer;
begin
...
T1:= ToolkPort.Create(false);
T1.FreeOnTerminate:= True;
Но в самом потоке не знаю, как вызвать процедуру из основного потока, что бы она продолжала слушать ком порт и обрабатывать пакеты, а в случае чего еще и приостанавливать поток основной программы и выводить модальное окно с предупреждением? и Так же в потоке ловить пакет выхода из спячки и убирать модальное окно
Код:
unit U_PortToolk;
interface
uses
Classes, CPortCtl, ExtCtrls, CPort, Dialogs, Windows, Messages,
SysUtils, Formirovatel_Paketov, U_StopModal;
type
ToolkPort = class(TThread)
ComPort: TComPort;
private
protected
procedure Execute; override;
end;
implementation
uses
U_Main;
procedure ToolkPort.Execute;
begin
{Вот здесь не знаю как правильно вызвать обработчик TF_Main.ComPort1RxChar, чтобы и в цикле он реагировал
на приходящие пакеты}
until Terminated;
end;
end.
Что в Execute потока прописать, что бы корректно все работало? Не заново же дублировать весь код обработчика TF_Main.ComPort1RxChar...
Спасибо всем кто откликнется