Обработка и сохранение исключений в параллельных задачах с использованием IOmniParallelTask в OTL
Вопрос, который стоит перед разработчиками, работающими с параллельными задачами в среде Delphi, заключается в правильной обработке и сохранении исключений. В частности, рассматривается проблема с использованием компонента IOmniParallelTask из библиотеки OTL, когда не удаётся корректно обработать исключения, возникшие в процессе выполнения задач.
Описание проблемы
Пользователь столкнулся с проблемой, когда не удаётся сохранить информацию об исключении в свойстве IOmniTaskControl.FatalException, несмотря на то, что в документации OTL указано, что должно быть возможным. Это приводит к тому, что исключения, возникающие в процессе выполнения задач, не доступны для обработки в обработчике завершения задач.
Пример кода, который должен был обработать исключение:
procedure TFormMain.TaskToExecute;
begin
Winapi.Windows.Sleep(2000);
raise Exception.Create('async operation exeption');
end;
procedure TFormMain.HandleOnTaskThreadTerminated(const task: IOmniTaskControl);
begin
if not Assigned(task.FatalException) then
Exit;
memo.Lines.Add('an exception occured: ' + task.FatalException.Message);
end;
Проблема в том, что свойство task.FatalException остаётся не назначенным, и в коде отсутствует понимание причин этого.
Подтверждённый ответ
Проблема кроется в том, что Parallel.ParallelTask хранит информацию об исключении в локальном поле, которое не синхронизировано с свойством IOmniTaskControl.FatalException. Это является недостатком абстракционного слоя.
Для решения проблемы в текущей версии OTL предлагается вызвать метод WaitFor в обработчике завершения, что позволит перехватить исключение:
procedure TFormMain.HandleOnTaskThreadTerminated(const task: IOmniTaskControl);
begin
try
fTask.WaitFor(0);
except
on E: Exception do
memo.Lines.Add('an exception occured: ' + E.Message);
end;
CleanupTask;
end;
Также было отмечено, что в IOmniParallelTask были добавлены свойства DetachException, FatalException и IsExceptional, что позволяет обрабатывать исключения напрямую:
procedure TFormMain.HandleOnTaskThreadTerminated(const task: IOmniTaskControl);
begin
if not Assigned(fTask.FatalException) then
Exit;
memo.Lines.Add('an exception occured: ' + fTask.FatalException.Message);
CleanupTask;
end;
Однако стоит отметить, что подход с использованием IOmniParallelTask.FatalException работает только для случая с одной задачей (.NumTasks(1)). В общем случае следует использовать обработчик OnStop:
procedure TFormMain.btnExecuteTaskClick(Sender: TObject);
begin
if Assigned(fTask) then
Exit;
memo.Lines.Add('task has been started..');
fTask := Parallel.ParallelTask.NoWait.NumTasks(1);
fTask.OnStop(HandleOnStop);
fTask.Execute(TaskToExecute);
end;
procedure TFormMain.HandleOnStop;
begin
if not Assigned(fTask.FatalException) then
Exit;
memo.Lines.Add('an exception occured: ' + fTask.DetachException.Message);
TThread.Queue(nil, CleanupTask);
end;
Таким образом, разработчикам необходимо быть внимательными при работе с параллельными задачами и использовать предоставленные средства OTL для корректной обработки исключений.
**Описание**: Вопрос связан с разработкой в среде Delphi, где рассматривается проблема обработки и сохранения исключений в параллельных задачах с использованием компонента `IOmniParallelTask` из библиотеки OTL, и поиск решения для сохранения информации о
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.