我有一个使用最新版EurekaLog的Delphi 10项目。我目前正在使用EurekaLog来帮助我调试生产客户端中的问题。
我注意到EurekaLog没有注册线程中发生的错误。在我开始阅读之后,我发现我需要从TThread
更改为TThreadEx
,并在Execute
覆盖方法的开头添加以下代码。
SetEurekaLogStateInThread(ThreadID, true);
尽管如此,当发生错误时,它不会在EL
文件中生成事件。
如果我在ExceptionManager.StandardEurekaError('TThrdSincArquivos.Execute => ' + ex.Message);
上添加try..except
,则会记录。但是堆栈跟踪显示为在我调用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
,但我得到的堆栈错误,我得到了对话框。
答案 0 :(得分:0)
使用TThread
类时-将线程异常保存到you are supposed to handle in some way的.FatalException
属性中。要么来自线程事件,要么来自其他(调用者)线程。 EurekaLog不会破坏此行为。例如。启用EurekaLog时,以前编写的代码将不会更改其行为。这样,您正确编写的代码在和下都可以在没有EurekaLog的情况下正常工作。
您的代码当前如何处理线程异常?您是否正在执行类似ShowMessage
或自定义日志记录的操作?这显然不适用于EurekaLog,它不知道您正在使用ShowMessage
或您自己的自定义日志记录代码来处理异常。您可能希望在调用者线程中使用类似Application.ShowException
或re-raise
之类的东西。
如果由于某种原因您不能使用默认的RTL / VCL处理(由EurekaLog挂接)-那么您需要告诉EurekaLog您想处理这个特殊异常。例如,来自docs:例如,您可以使用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;
您可能想要设置异常过滤器或使用事件来禁用线程异常对话框,因为大概您已经自己处理了异常(例如已经显示的消息)。
还有更多的方法来处理线程中的异常,EurekaLog's docs说明了每种线程的情况(例如BeginThread
,TThread
,线程池等) 。)和几种可能的选择。将所有这些信息打包成一个答案是不合理的。
如果由于某种原因,您没有用于处理.FatalException
的{{1}}属性的代码-那么您可以使用TThread
类及其TThreadEx
属性来处理异常自动退出线程,如here所述:
.AutoHandleException
但是,请注意,如果您以后决定禁用EurekaLog,则您的代码将无法正常工作(例如,将忽略异常)。因为如果您从项目中删除EurekaLog,则您的项目将没有代码来处理线程异常!
P.S。
我需要从
type TMyThread = class(TThreadEx) protected procedure Execute; override; end; procedure TMyThread.Execute; begin // ... your code ... end; procedure TForm1.Button1Click(Sender: TObject); var Thread: TMyThread; begin Thread := TMyThread.Create(True, 'My thread'); Thread.AutoHandleException := True; // <- added Thread.FreeOnTerminate := True; Thread.Start; Thread := nil; // never access thread var with FreeOnTerminate after Start end;
更改为TThread
,并添加以下内容 代码在我的TThreadEx
覆盖方法的开头。Execute
这有点不正确:您可以做一个或另一个,但不能两者都做。还有其他方法可以告诉EurekaLog它应该在此线程中挂钩异常。
基本上,异常生命有两个阶段:引发和处理。当用默认的RTL / VCL代码实现时,EurekaLog会钩住这两个阶段。您需要明确指出要挂接的线程,因为您可能想忽略无法控制的系统/第三方线程。因此,在RTL / VCL中不存在对SetEurekaLogStateInThread(ThreadID, true);
的默认处理。这就是为什么没有什么可钩的。