【问题标题】:Is this a correct way of using OmniThreadLibrary - terminate the existing one then create a new one?这是使用 OmniThreadLibrary 的正确方法吗 - 终止现有的然后创建一个新的?
【发布时间】:2012-03-29 19:20:34
【问题描述】:

我使用优秀的 OmniThreadLibrary 库来实现线程化源码解析,程序需要放弃现有的解析,每当源代码发生变化时重新开始解析。

我使用下面显示的代码 sn-p 执行此操作,它是正确的方法吗?我还需要检查ThreadedParseHtml函数中线程的Terminated属性吗?

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:回答 Rob 的问题:

    1234563被终止,因为它的解析已经完成。
  1. 代码背后的逻辑是,这是一个代码编辑器,在任何代码编辑时,都会启动一个线程将源代码解析为内部树表示,以防新代码编辑发生但之前的解析线程没有被编辑,程序将首先强制之前的解析线程然后启动一个新的解析线程。这可能不是一个好方法...

编辑 4:阅读this similar SO question 后,我将代码更改为不带参数调用FParserThread.Terminate,这意味着,如果我理解正确,该语句只会发出线程结束的信号,在实际的线程任务中,如果Terminated 属性为True,我应用逻辑退出线程执行。

现在的连线是,在Tracetool 的帮助下,我发现在调用FParserThread.Terminate 之后OnTaskMessage 事件(我清理内存的地方)不会再次触发,这就是导致内存泄漏的原因....

【问题讨论】:

  • 好的,我想我必须在解析例程中检查 Thread 对象的 Terminiated 标志...
  • 请添加有关新信息的更多详细信息。 FParserThread “自行完成”是什么意思,为什么要让 FParserThread 调用 Terminate?
  • Rob,我添加了 Edit 3 来回答您的问题,感谢您对迟到的回复感到抱歉。
  • OK,最后,我发现问题的发生是因为没有触发 OnTaskMessage 事件,在调用 Terminate() 方法之后...我找到了一个workround - 在线程任务执行代码中,在如果线程被终止,那里有空闲的内存......

标签: delphi omnithreadlibrary


【解决方案1】:

您不必检查关联任务中的Terminated 属性。您正在调用Terminate(1),如果线程没有在您指定的 1 毫秒窗口内结束,它将强制终止线程。

但是,强行杀死一个线程确实不是一个好主意。当您杀死该线程时,该线程可能拥有互斥锁或临界区,因此杀死它会使共享数据处于不一致的状态。这可能会对您的整个程序产生不利影响。

最好是通知您的线程您希望它终止,但给它一个更现实的终止期限。在另一个线程中,您应该偶尔检查线程是否已被要求终止,然后让它自己优雅地终止。

如果线程没有在规定的时限内结束,那么你的问题就更大了,强行杀死它并不能解决问题。

【讨论】:

  • 谢谢 Rob,这是我想要的答案,我在问了这个 SO 问题后进行了一些研究后才想出来的;)
  • Rob,抱歉,我重新打开了这个问题,如果您想进一步帮助我,请查看我的编辑 :)
【解决方案2】:

在这里,在使用 OmniThreadLibrary 超过 2 年之后,我的结论是停止 OTL 任务的正确方法是使用取消令牌。下面的代码示例。

在调用者线程(通常是主线程)中,调用:

//this will tell (not kill) the thread identified by myTask to stop.
myTask.CancellationToken.Signal;

在被调用线程中必须定期检查task.CancellationToken.IsSignaled属性,如果为真则退出执行,线程终止将由系统和OTL处理:

if task.CancellationToken.IsSignaled then
  Exit;

【讨论】:

    猜你喜欢
    • 2018-05-06
    • 1970-01-01
    • 2012-06-24
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    • 2019-09-01
    • 2012-05-11
    相关资源
    最近更新 更多