При работе с многопоточностью в Delphi часто возникает необходимость выполнить длительную задачу в рабочем потоке и затем оповестить главный поток о завершении этой задачи. В этой статье мы рассмотрим, как это можно сделать, используя пример вызова веб-службы в рабочем потоке и оповещение главного потока из датамодуля.
Проблема
У нас есть датамодуль, не имеющий своего окна, и мы хотим выполнить вызов веб-службы в рабочем потоке и затем оповестить главный поток о результате. В основном потоке у нас есть форма с приватным полем (приватная строка), в которое рабочий поток будет записывать результат вызова веб-службы. После завершения вызова веб-службы рабочий поток должен уведомить главный поток о том, что результат готов.
Решение
Для решения этой проблемы мы можем использовать подход с сообщениями (PostMessage) или Events. Рассмотрим оба подхода.
1. Подход с сообщениями
Для отправки сообщений из рабочего потока в главный поток мы можем использовать функцию PostMessage. Чтобы это сделать, нам нужно иметь доступ к оконной процедуре главного потока. Однако, датамодуль не имеет своего окна и, следовательно, не имеет оконной процедуры. В этом случае мы можем использовать функцию AllocateHwnd, чтобы создать скрытое окно и использовать его оконную процедуру для приема сообщений.
Вот пример кода, демонстрирующий этот подход:
type
TMyDataModule = class(TDataModule)
private
FWorkerThread: TMyThread;
FWebServiceResponseXML: TWebServiceResponseXML;
FWinHandle: HWND;
procedure OnWebServiceCallComplete(var Message: TMessage);
public
procedure StartWorkerThread;
end;
TMyThread = class(TThread)
private
FResponseXML: TWebServiceResponseXML;
FWinHandle: HWND;
protected
procedure Execute; override;
public
constructor Create(WinHandle: HWND);
end;
constructor TMyThread.Create(WinHandle: HWND);
begin
inherited Create(False);
FWinHandle := WinHandle;
end;
procedure TMyThread.Execute;
begin
inherited;
CoInitialize(nil);
try
// Выполняем вызов веб-службы и записываем результат в FResponseXML
PostMessage(FWinHandle, WM_WEBSERVCALL_COMPLETE, 0, 0);
finally
CoUninitialize;
end;
end;
procedure TMyDataModule.StartWorkerThread;
begin
FWinHandle := AllocateHWND(nil);
FWorkerThread := TMyThread.Create(FWinHandle);
FWorkerThread.FreeOnTerminate := True;
FWorkerThread.Resume;
end;
procedure TMyDataModule.OnWebServiceCallComplete(var Message: TMessage);
begin
// Обрабатываем результат вызова веб-службы в FWebServiceResponseXML
end;
2. Подход с Events
В качестве альтернативы подходу с сообщениями, мы можем использовать Events для оповещения главного потока о завершении вызова веб-службы. Для этого нам нужно добавить событие в класс рабочего потока и вызвать его в методе Execute после завершения вызова веб-службы.
Вот пример кода, демонстрирующий этот подход:
type
TMyDataModule = class(TDataModule)
private
FWorkerThread: TMyThread;
FWebServiceResponseXML: TWebServiceResponseXML;
procedure OnWebServiceCallComplete(Sender: TObject);
public
procedure StartWorkerThread;
end;
TMyThread = class(TThread)
private
FResponseXML: TWebServiceResponseXML;
FOnWebServiceCallComplete: TNotifyEvent;
protected
procedure Execute; override;
public
property OnWebServiceCallComplete: TNotifyEvent read FOnWebServiceCallComplete write FOnWebServiceCallComplete;
end;
procedure TMyThread.Execute;
begin
inherited;
CoInitialize(nil);
try
// Выполняем вызов веб-службы и записываем результат в FResponseXML
if Assigned(FOnWebServiceCallComplete) then
FOnWebServiceCallComplete(Self);
finally
CoUninitialize;
end;
end;
procedure TMyDataModule.StartWorkerThread;
begin
FWorkerThread := TMyThread.Create(False);
FWorkerThread.FreeOnTerminate := True;
FWorkerThread.OnWebServiceCallComplete := OnWebServiceCallComplete;
FWorkerThread.Resume;
end;
procedure TMyDataModule.OnWebServiceCallComplete(Sender: TObject);
begin
// Обрабатываем результат вызова веб-службы в FWebServiceResponseXML
end;
Заключение
В этой статье мы рассмотрели два подхода к оповещению главного потока о завершении вызова веб-службы в рабочем потоке из датамодуля: подход с сообщениями и Events. Каждый из этих подходов имеет свои преимущества и недостатки, и выбор между ними зависит от конкретных требований вашего проекта.
В данном контексте рассматривается использование многопоточности в Delphi для выполнения вызова веб-службы в рабочем потоке и оповещения главного потока из датамодуля о результате выполнения.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.