如何捕获线程中的异常?

时间:2015-09-02 14:51:57

标签: multithreading delphi c++builder

我的网络服务器基于Delphi / DataSnap。 当服务器方法引发异常时,我该如何处理它?<​​/ p>

我尝试Application.OnException但它不起作用,因为每个连接都是一个新线程,它只适用于IDE线程。

我想管理它们以便在日志文件中添加数据。

更新

正如@Remy Lebeau所说,我无法控制线程的创建。它是一个基于DataSnap的应用程序,可用作Web Api服务器。一个TDSServerClass个组件实例TServerMethods类。然后,当Web连接到达时,DataSnap会创建一个新线程并调用我的TServerMethods方法。如果在方法中引发异常,则会丢失,因为每个线程都有其堆栈。使用Application.OnException,我只能从IDE线程中捕获未处理的异常。我想要做的是在日志文件中记录任何手持设备异常。

2 个答案:

答案 0 :(得分:1)

来自System.Classes.TThread.FatalException文档:

  

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

如果Execute对象的TThread方法发生异常,则会分配FatalException属性并且线程终止。

您可以检查实现其OnTerminate事件的线程中是否发生异常:

procedure TForm1.YourThreadTerminate(Sender: TObject);
var
  ex: Exception;
begin
  ex := Exception(TYourThread(Sender).FatalException);
  if Assigned(ex) then
    //an exception has occurred: your code here
end;

这是您可以将事件分配给线程的方法:

var
  yourThread: TYourThread;
begin
  yourThread := TYourThread.Create(True);
  yourThread.OnTerminate := YourThreadTerminate;
  yourThread.Start;
end;

答案 1 :(得分:0)

您可能需要挂钩异常处理机制本身 - JCL具有执行此操作的代码,或者您可以使用第三方库,如madExceptEurekaLog或其他。它们还收集堆栈跟踪和其他有用的信息,以了解导致异常的原因。 我不久前在Datasnap DCOM服务器中使用JCL将未处理的异常记录到自定义事件日志中。如果您要写入文件,请注意并发访问,因为多个线程可能会尝试写入它。此外,Event Tracing for Windows(ETW)可能是一种更好的,但更复杂的方式,可以记录到文件以进行诊断。 无论如何,在这种应用程序中,最好处理“预期的”异常,并且永远不要让它们传播到通用处理程序。当然,能够捕获和记录“意外”的是有用的。