如何捕获后台线程中引发的未处理异常?

时间:2018-09-18 15:16:26

标签: delphi firemonkey

我习惯于执行像这样的匿名线程:

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

但是问题是,如果在执行过程中出现某些未处理异常,则不会警告我!对于主线程,我们有Application.OnException。我们的后台线程有类似的东西吗?

4 个答案:

答案 0 :(得分:11)

TThread具有公共FatalException属性:

  

如果Execute方法引发该方法中未捕获和处理的异常,则线程终止并将FatalException设置为该异常的异常对象。 应用程序可以从OnTerminate事件处理程序中检查FatalException,以确定线程是否由于异常而终止。

例如:

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;

答案 1 :(得分:5)

N̶o̶,̶̶t̶h̶e̶r̶e̶̶i̶s̶̶n̶o̶t̶h̶i̶n̶g̶̶s̶i̶m̶i̶l̶a̶r̶̶f̶o̶r̶̶a̶̶b̶a̶c̶k̶g̶r̶o̶u̶n̶dhanhant,(最好的解决方案是始终绝对确保永远不要让异常从线程中逸出。理想情况下,您的线程过程应如下所示:

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

答案 2 :(得分:1)

Ok, finally I got the best answer :

Assign the global ExceptionAcquired procedure to our own implementation (it is nil by default). This procedure gets called for unhandled exceptions that happen in other threads than the main thread.

ExceptionAcquired := MyGlobalExceptionAcquiredHandler; 

答案 3 :(得分:-1)

J ...和雷米·勒博(Remy Lebeau)的回答对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这样的全局var被声明为threadvar,因此一切工作正常,甚至可以检索堆栈跟踪!

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