Корректная обработка результатов параллельного пинга хостов в Delphi
При работе с параллельными задачами в Delphi, особенно при использовании библиотек типа OmniThreadLibrary, могут возникать проблемы с корректной обработкой результатов в основном потоке. Одной из таких проблем является некорректное поведение при работе с переменными, захваченными в замыкании, как в примере, предоставленном пользователем Shrinavat.
Проблема
При использовании цикла для запуска параллельных задач пинга каждого хоста, переменная i не корректно захватывается в замыкании, что приводит к неожидаемым результатам. В некоторых случаях одни и те же хосты пингуются несколько раз, а для других хостов результаты не обрабатываются вовсе. Кроме того, могут появляться некорректные данные.
Решение Shrinavat
Shrinavat предложил решение, заключающееся в передаче ID и IP в качестве параметров в функцию CreatePingTask, которая запускает параллельную задачу. Это гарантирует, что каждая задача получит правильные значения ID и IP. Для синхронизации с главным потоком и обновления интерфейса пользователя используется task.Invoke.
procedure Test;
var
arr_id: TArray<LongWord>;
arr_ip: TArray<string>;
procedure CreatePingTask(const id: LongWord; const ip: string);
begin
Parallel.Async(
procedure (const task: IOmniTask)
var
PingResult: Boolean;
begin // background thread
// Simulate ping
PingResult := Random(2) = 1; // random result for demonstration
Sleep(Random(5000)); // simulate ping delay
// in the main thread
task.Invoke(
procedure
begin
mmoLog.Lines.Add(Format('PingResult=%s, rec_id=%d, rec_ip=%s', [PingResult.ToString, id, ip]));
end);
end);
end;
begin
arr_id := [1,2,3,4,5,6,7];
arr_ip := ['192.168.16.1','192.168.16.2','192.168.16.3','192.168.16.4','192.168.16.5','192.168.16.6','192.168.16.7'];
for var i := Low(arr_id) to High(arr_id) do
CreatePingTask(arr_id[i], arr_ip[i]);
end;
Альтернативное решение с использованием TTask
В качестве альтернативы можно использовать компонент TTask из пакета System.SysUtils для запуска параллельных задач. При использовании TTask, переменные корректно захватываются в задаче, что исключает описанную выше проблему.
procedure Test;
var
arr_id: TArray<LongWord>;
arr_ip: TArray<string>;
Tasks: TArray<TTask>;
begin
arr_id := [1,2,3,4,5,6,7];
arr_ip := ['192.168.16.1','192.168.16.2','192.168.16.3','192.168.16.4','192.168.16.5','192.168.16.6','192.168.16.7'];
SetLength(Tasks, Length(arr_id));
for var i := Low(arr_id) to High(arr_id) do
begin
Tasks[i] := TTask.Create(nil);
Tasks[i].OnExecute := procedure (Sender: TObject)
begin
// Simulate ping
var PingResult: Boolean;
PingResult := Random(2) = 1; // random result for demonstration
Sleep(Random(5000)); // simulate ping delay
// in the main thread
mmoLog.Lines.Add(Format('PingResult=%s, rec_id=%d, rec_ip=%s', [PingResult.ToString, arr_id[i], arr_ip[i]]));
end;
Tasks[i].Start;
end;
for var i := Low(arr_id) to High(arr_id) do
Tasks[i].WaitFor;
end;
В этом примере мы создаем массив задач и для каждой задачи устанавливаем обработчик события OnExecute. В обработчике выполняется симуляция пинга и добавление результата в список. После запуска всех задач, мы ждем завершения каждой из них с помощью WaitFor.
Заключение
При работе с параллельными задачами в Delphi важно правильно обрабатывать результаты в основном потоке. В данной статье мы рассмотрели проблему, связанную с некорректным поведением переменных, захваченных в замыкании, и предложили два решения: одно с использованием библиотеки OmniThreadLibrary, а другое с использованием компонента TTask из пакета System.SysUtils. Оба решения гарантируют корректную обработку результатов параллельного пинга хостов в Delphi.
В данном контексте рассматривается проблема корректной обработки результатов параллельного пинга хостов в Delphi, когда используются библиотеки для работы с параллельными задачами, такие как OmniThreadLibrary. При работе с циклами для запуска параллельных
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.