Multithreading 在没有与Eurekalog对话的情况下,在线程内正确记录日志
我有一个Delphi10项目,使用最新版本的EurekaLog。我目前正在使用EurekaLog来帮助我调试生产客户机中的问题 我注意到EurekaLog没有记录线程中发生的错误。开始阅读之后,我发现我需要从Multithreading 在没有与Eurekalog对话的情况下,在线程内正确记录日志,multithreading,delphi,eurekalog,Multithreading,Delphi,Eurekalog,我有一个Delphi10项目,使用最新版本的EurekaLog。我目前正在使用EurekaLog来帮助我调试生产客户机中的问题 我注意到EurekaLog没有记录线程中发生的错误。开始阅读之后,我发现我需要从TThread更改为TThreadEx,并在Execute重写方法的开头添加以下代码 SetEurekaLogStateInThread(ThreadID, true); SetEurekaLogStateInThread(ThreadID, true); 尽管如此,当发生错误时,它不会
TThread
更改为TThreadEx
,并在Execute
重写方法的开头添加以下代码
SetEurekaLogStateInThread(ThreadID, true);
SetEurekaLogStateInThread(ThreadID, true);
尽管如此,当发生错误时,它不会在EL
文件中生成事件
如果我添加ExceptionManager.standareurekaerror('tthrdss.Execute=>'+ex.Message)代码>在try。但是堆栈跟踪显示为错误发生在我调用StandardEurekaLog()
的行上,而不是实际发生错误的行上。这违背了整件事的目的
另一个问题是,它显示了一个对话框,我不想看到,因为错误发生在后台线程中。我只想把它记录下来。我应该得到一个对话框,只有在主线程上有错误
如何在线程内实现这些结果
- 用正确的堆栈记录错误
- 当在主线程上时,显示对话框,但在线程内,只需记录而不显示对话框
编辑
下面是我的EurekaLog多线程配置
以下是我的线程声明:
unit ThrdSincArquivos;
interface
uses
System.Classes, System.SysUtils, System.Generics.Collections, REST.Client, REST.Types,
System.JSON, Data.DB, Datasnap.DBClient, FireDAC.Comp.Client, FireDAC.Stan.Param, System.SyncObjs, EBase, EExceptionManager, EClasses;
type
TThrdSincArquivos = class(TThreadEx)
private
我的线程正在创建
constructor TThrdSincArquivos.Create(pPrimeiraExec: boolean; tipoSincParam: TTipoSinc);
begin
inherited Create(true);
NameThreadForDebugging('TThrdSincArquivos');
primeiraExec := pPrimeiraExec;
tipoSinc := tipoSincParam;
executadoThreadSinc := false;
FreeOnTerminate := true
end;
开始我的执行
procedure TThrdSincArquivos.Execute;
var
contador: Integer;
begin
inherited;
try
和执行的结束
except
on ex: Exception do
begin
oLog.GravarLog(ex, 'TThrdSincArquivos.Execute => FIM');
end;
end;
end;
它拒绝将任何异常记录到Elf文件中。我试着在我自己的日志程序之后加一个加薪,但还是没有用。它应该记录,但它不是,除非我显式调用StandardEurekaError
,但是我得到了错误的堆栈,并且得到了对话框。当您使用TThread
类时,它将线程异常保存到.FatalException
属性,该属性。来自线程事件或其他(调用方)线程。尤里卡洛并没有破坏这种行为。例如,当您启用EurekaLog时,您以前编写的代码不会改变其行为。这样,正确编写的代码在使用和不使用EurekaLog的情况下都能正常工作
您的代码当前如何处理线程异常?您正在执行类似于ShowMessage
或自定义日志记录的操作吗?这显然不适用于EurekaLog,它不知道您正在使用ShowMessage
或您自己的自定义日志代码处理异常。您可能需要调用程序线程中的Application.ShowException
或re-raise
之类的内容
如果由于某种原因不能使用默认的RTL/VCL处理(由EurekaLog钩住),那么您需要告诉EurekaLog您想要处理这个特殊的异常。例如,from:您可以使用(例如)HandleException(E)代码>来自EBase
单位:
Thread.WaitFor;
if Assigned(Thread.FatalException) then
begin
// Your old code is here
// Do your own thing: show message, log, etc.
// Tell EurekaLog to do its thing:
HandleException(Thread.FatalException);
end;
您可能希望设置异常过滤器或使用事件来禁用线程异常的对话框,因为您可能已经自己处理了异常(例如,已显示消息)
处理线程中异常的方法有很多,并用几个可能的选项说明每个线程的情况(如BeginThread
、TThread
、线程池等)。将所有这些信息打包成一个答案是不合理的
如果由于某种原因,您没有处理TThread
的.FatalException
属性的代码,则可以使用TThreadEx
类及其.AutoHandleException
属性在线程退出时自动处理异常,如下所述:
这有点不正确:你可以做一个或另一个,但不能两者都做。还有其他方法告诉EurekaLog它应该在这个线程中钩住异常
基本上,异常生命有两个阶段:提升和处理。在默认RTL/VCL代码中实现时,EurekaLog钩住这两个阶段。您需要明确指出要挂接哪些线程,因为您可能希望忽略无法控制的系统/第三方线程。RTL/VCL中不存在TThread
的默认处理。这就是为什么没有什么好挂的。顺便说一句,没有像XE10这样的东西会让尤里卡洛非常失望。我个人使用MadExcept,并强烈推荐它。@Pascal您可以使用。该组件提供[OneExceptionAction]()事件,允许在Eureka处理异常时跳过不必要的步骤。事件具有AEurekaAction参数,用于定义要执行的步骤。ShowingExceptionInfo的参数值表示Eureka希望显示错误对话框。如果不想显示对话框,只需将AExecute参数设置为False即可。@Pascal还有AEExceptionInfo参数-它是一个具有两个有用属性的类。您可以检查ThreadID、ThreadException和SynchronizeException,以了解后台线程中是否出现异常。
SetEurekaLogStateInThread(ThreadID, true);