![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
|
|
#1
|
|||
|
|||
|
Доброе утро!
У меня возник вопрос. Пару месяцев назад начал работать с делфи. Подскажите как реализовать следующую задачу. Вот как сейчас работает моя программа: - слушает определенный порт - если на этот порт приходит запрос от клиента, то обрабатывает этот запрос - если в момент обработки запроса от клиента приходит еще один запрос, то его необходимо отклонить Запрос представляет из себя строку с параметрами. Получив эти параметры программа вызывает функцию из Dll, которая отправляет эти параметры на устройство через COM- порт. Устройство обрабатывает данные и возвращает ответ. Суть проблемы. Обработка данных устройством занимает 15-20 секунд, и в это время все запросы приходящие на порт, который слушается -- становятся в очередь и не обрабатываются пока не отработает функция. Это не допустимо. Необходимо, чтобы в случае занятости -- клиент сразу получал ответ. Как наладить параллельную работу прослушки порта и остальной работы программы? Вот участок кода, который обрабатывает запросы: Код:
if ServerSocket.Socket.ActiveConnections = 1 then
begin
//тут читаем параметры запроса
CheckRequest; // обрабатывает запрос (15-20 секунд);
GetParam:='';
exit;
end
else
begin
ServerSocket.Socket.Connections[ServerSocket.Socket.ActiveConnections-1].SendText('Сервер не доступен');
Application.ProcessMessages;
Buffer.Lines.Insert(0,'Отключаем лишний коннект');
Application.ProcessMessages;
ServerSocket.Socket.Connections[ServerSocket.Socket.ActiveConnections-1].Close;
Application.ProcessMessages;
ConNum;
end; |
|
#2
|
||||
|
||||
|
завести флаг занятости устройства. устанавливать его при получении запроса от клиента и сбрасывать после получения ответа от устройства. в обработчике запросов от клиентов проверять флаг занятости и отвергать запросы (сообщать клиенту о занятости) при его активности.
|
|
#3
|
||||
|
||||
|
...ну и конечно CheckRequest обрабатывать в отдельном потоке.
|
|
#4
|
||||
|
||||
|
Предроложим что:
BusyFlag - глобальная переменная в рамках данного модуля TCheckRequestThread - поток который обрабатывает запрос на внешнем устройстве, после обработки данных он самоуничтожается. Код:
if ServerSocket.Socket.ActiveConnections = 1 then
begin
//тут читаем параметры запроса
if not BusyFlag then
begin
BusyFlag:=True;
TCheckRequestThread.Create; //запускаем поток (возможно, и даже скорее всего,
// в конструктор нужно быдет передать некоторые параметры)
// CheckRequest; // обрабатывает запрос (15-20 секунд);
end
else
begin
//тут отклоняем запросы пользователей
end;
GetParam:='';
exit;
end
else
begin
ServerSocket.Socket.Connections[ServerSocket.Socket.ActiveConnections-1].SendText('Сервер не доступен');
Application.ProcessMessages;
Buffer.Lines.Insert(0,'Отключаем лишний коннект');
Application.ProcessMessages;
ServerSocket.Socket.Connections[ServerSocket.Socket.ActiveConnections-1].Close;
Application.ProcessMessages;
ConNum;
end; |
|
#5
|
|||
|
|||
|
Цитата:
Понял. Спасибо попробую. Сейчас читаю про потоки. Возник вопрос: Вот стандартный пример для обращения из потока к свойствам vcl компонент Код:
procedure MyThread.UpdateCaption; begin Form1.Caption := 'Updated in a thread'; end; procedure MyThread.Execute; begin Synchronize(UpdateCaption); end; возможно ли через процедуру Synchronize обращаться напрямую к процедурам объекта TForm например есть вот такое Код:
procedure TForm1.UpdateCaption; begin Caption := 'Updated in a thread'; end; как можно вызвать эту процедуру в потоке? Это будет верно? Код:
procedure MyThread.Execute; begin Synchronize(TForm1.UpdateCaption); end; Последний раз редактировалось M.A.D.M.A.N., 22.10.2013 в 09:48. |
|
#6
|
|||
|
|||
|
Так вызывать нельзя - метод должен быть описан внутри класса потока. Вызывай свой CheckRequest в MyThread.Execute; В твоем случае отсутствие синхронизации не приведет к сбою. Естественно CheckRequest должен быть описан в классе TMyThread.
Установи свойство MyThread.FreeOnTerminate в true. Флаг использовать не обязательно, достаточно проверить является ли MyThread nil. Если поток выполняется, то отвечай клиенту, что "занято", если поток nil, то создавай поток и запускай его (Resume). Рекомендую почитать про потоки и методы синхронизации подробнее. Последний раз редактировалось Sibay, 21.10.2013 в 16:26. |
|
#7
|
|||
|
|||
|
Цитата:
Это у меня все реализовано. Флагом является проверка на уже существующий коннект. Если он есть, то все остальные запросы получают ответ о занятости устройства. НО, ответ о занятости не посылается, пока не отработает функция с COM портом. Т.о. все клиенты которые соединяются в момент работы программы с ком портом -- ожидают окончания этой работы и только потом получают ответы. Цитата:
Я только начал читать про потоки. Подскажите пожалуйста основные моменты, как в моем случае это реализовать Последний раз редактировалось M.A.D.M.A.N., 21.10.2013 в 15:15. |
|
#8
|
||||
|
||||
|
Цитата:
|
|
#9
|
|||
|
|||
|
подскажите можно ли из потока вызвать функцию(из длл).
Функция описана так в TForm: и как это правильно сделать. Код:
private SetComParams : function(Num: Byte; Rate: DWord): Byte; stdcall; Последний раз редактировалось M.A.D.M.A.N., 22.10.2013 в 09:48. |