我使用出色的OmniThreadLibrary库来实现线程化的源代码解析,该程序需要放弃现有的解析,并在源代码发生更改时重新启动解析。
我使用下面显示的代码段执行此操作,这是正确的方法吗?我还需要检查Terminated
函数中线程的ThreadedParseHtml
属性吗?
if FParserThread <> nil then
begin
FParserThread.RemoveMonitor;
FParserThread.Terminate(500);
end;
FParserThread := CreateTask(ThreadedParse);
FParserThread.SetParameter('SourceCode', Editor.Lines.Text);
FParserThread.MonitorWith(FParserThreadMonitor);
FParserThread.Run;
提前致谢!
编辑1:很抱歉再次提出这个问题,但是当我没有足够的时间通过调用
FParserThread
方法完成Terminate
本身时,我发现内存泄漏了。关于什么可能导致内存泄漏的任何想法?谢谢!编辑2:阅读this blog post,我仍然不知道问题可能出在哪里,因为在
ThreadedParse
的每个步骤之后,如果Terminated
正确,代码就会中断...编辑3:回答罗布的问题:
在OnTerminated事件处理程序(此处未显示)中,FParserThread设置为“ nil”,因此通过“ FParser自身完成”,我的意思是不执行
if FParserThread <> nil then
块,在这种情况下FParserThread会终止,因为它已经解析了完成了。代码背后的逻辑是,这是一个代码编辑器,在进行任何代码编辑时,都会启动一个线程将源代码解析为内部树表示形式,以防发生新的代码编辑但先前的解析很繁琐的情况。尚未编辑,该程序将首先强制使用先前的解析线程,然后再启动一个新的解析线程。这可能不是一个好方法...
编辑4:读取this similar SO question后,我将代码更改为不带参数调用
FParserThread.Terminate
,这意味着,如果我正确理解,该语句将仅指示线程结束,并且在实际的线程任务中,我应用了如果Terminated
属性为True
,则退出线程执行的逻辑。现在连接的是,在Tracetool的帮助下,我发现在调用
FParserThread.Terminate
后,不会再次触发OnTaskMessage
事件(我在其中清理内存),这就是导致内存泄漏的原因... 。
最佳答案
您不必在关联的任务中检查Terminated
属性。您正在调用Terminate(1)
,如果它未在指定的1 ms窗口内结束,则会强制杀死该线程。
但是,强制杀死线程实际上不是一个好主意。当您杀死该线程时,该线程可能拥有互斥体或关键部分,因此杀死该线程将使共享数据处于不一致状态。这可能会对您的整个程序产生不利影响。
更好的方法是通知线程您希望其终止,但给它一个更现实的终止期限。在另一个线程中,您应该偶尔检查是否要求该线程终止,然后让其正常终止。
如果线程没有在指定的时限内结束,则您遇到了更大的问题,强行杀死它并不能解决问题。
关于delphi - 这是使用OmniThreadLibrary的正确方法-终止现有的然后创建一个新的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9932013/