Как отловить необработанное исключение, которое возникает в фоновом потоке? - PullRequest
0 голосов
/ 18 сентября 2018

У меня есть привычка выполнять анонимный поток, например:

TThread.CreateAnonymousThread(
   procedure
   begin
     .....
   end).start;

Но проблема в том, что если во время выполнения возникнет исключение необработанное , то я не буду предупрежден оЭто!Для основного потока у нас есть Application.OnException.Есть ли у нас что-то подобное для фоновой темы?

Ответы [ 4 ]

0 голосов
/ 18 сентября 2018

Хорошо, наконец-то я получил лучший ответ:

Назначьте глобальную ExceptionAcquired процедуру для нашей собственной реализации (по умолчанию это nil).Эта процедура вызывается для необработанных исключений, которые происходят в других потоках, кроме основного потока.

ExceptionAcquired := MyGlobalExceptionAcquiredHandler; 
0 голосов
/ 18 сентября 2018

TThread имеет открытое свойство FatalException:

Если метод Execute вызывает исключение, которое не перехватывается и не обрабатывается в этом методе, потокзавершается и устанавливает FatalException для объекта исключения для этого исключения. Приложения могут проверять FatalException из обработчика событий OnTerminate, чтобы определить, завершился ли поток из-за исключения.

Например:

procedure TMyForm.DoSomething;
begin
  ...
  thread := TThread.CreateAnonymousThread(...);
  thread.OnTerminate := ThreadTerminated;
  thread.Start;
  ...
end;

procedure TMyForm.ThreadTerminated(Sender: TObject);
begin
  if TThread(Sender).FatalException <> nil then
  begin
   ...
  end;
end;
0 голосов
/ 18 сентября 2018

Ответ J ... и Реми Лебо хорош с тем, что предлагает Delphi, но мне нужно немного больше, и я наконец решил немного изменить модуль System.Classes

var
  ApplicationHandleThreadException: procedure (Sender: TObject; E: Exception) of object = nil;

function ThreadProc(const Thread: TThread): Integer;
  ...
  try
    Thread.Execute;
  except
    Thread.FFatalException := AcquireExceptionObject;
    if assigned(ApplicationHandleThreadException) and
       assigned(Thread.FFatalException) and
       (Thread.FFatalException is Exception) and
       (not (Thread.FFatalException is EAbort)) then
      ApplicationHandleThreadException(Thread, Exception(Thread.FFatalException));
  end; 

в этомТаким образом, вам просто нужно присвоить ApplicationHandleThreadException для обработки необработанного повышения исключений в любом TThread.Вам не нужно беспокоиться о многопоточности, потому что глобальные переменные типа ExceptAddr объявлены как threadvar, поэтому все работает отлично, даже для получения трассировки стека!

https://quality.embarcadero.com/browse/RSP-21269

0 голосов
/ 18 сентября 2018

Нет, не знаю, как всегда!В идеале, ваши потоковые процедуры должны выглядеть примерно так:

TThread.CreateAnonymousThread(
   procedure
   begin
     try
       { your code}
     except
       {on E : Exception do}
       {... handle it!}            
     end;
   end).start;
...