如何解决预计未释放Omnithread未观察到的嵌套线程
背景
我的旗舰应用似乎泄漏了内存。好吧,不是真的,而是在运行时。调查表明,当应用关闭时,内存“泄漏”已解决,但在关闭之间没有解决。
我正在使用后台线程,即iself启动了另一个线程。这两个线程(父线程和子线程)都是“未观察到”的,这将导致在踩踏完成后释放并释放TOmniTaskControl对象。
实验代码
procedure TfrmMain.MyTestProc(const aTask: IOmniTask);
begin
sleep(100);
SGOutputDebugStringFmt('%s.MyTestProc for %s',[ClassName,aTask.Name]);
sleep(100);
end;
procedure TfrmMain.MynestedTestProc(const aTask: IOmniTask);
var lTask:IOmniTaskControl;
begin
sleep(100);
SGOutputDebugStringFmt('%s.MyTestProc for %s',aTask.Name]);
lTask:=CreateTask(MyTestProc,'nestedTask');
lTask.Unobserved.Run;
sleep(100);
end;
procedure TfrmMain.btSimpleThreadClick(Sender: TObject);
var lTask:IOmniTaskControl;
begin
lTask:=CreateTask(MyTestProc,'SimpleThread');
lTask.Unobserved.Run;
end;
procedure TfrmMain.btnestedThreadClick(Sender: TObject);
var lTask:IOmniTaskControl;
begin
lTask:=CreateTask(MynestedTestProc,'nestedThread');
lTask.Unobserved.Run;
end;
调试时,在TOmniTaskControl.Destroy
上设置断点,并在手表TOmniTaskControl.Name
上看到以下内容:
- btSimpleThreadCLick:
- 要创建用于'SimpleThread'的TOmniTaskControl
- “ SimpleThread”的TOmniTaskControl被破坏
- btnestedThreadCLick:
问题:“ nestedTask”的TOmniTaskControl未被销毁。另一个问题是,也没有调用OnTerminate。
然后,在关闭应用程序时,“ SimpleThread”的TOmniTaskCOntrol
被销毁。 (而且,OnTherminate
被解雇了)
我想出了解决方案,似乎可以解决问题。然而,问题是,我通常不从手头就有TOmniEventMonitor的形式运行子线程。因此,我必须为此创建一个 global TOmniEventMonitor
对象。
但这不是UnObserved
方法的全部要点吗?
procedure TfrmMain.MynestedTestProc(const aTask: IOmniTask);
var lTask:IOmniTaskControl;
begin
sleep(100);
SGOutputDebugStringFmt('%s.MyTestProc for %s','nestedTask');
lTask.MonitorWith(OmniEventMonitor).Run; // OmniEventMonitor is a component on my form
sleep(100);
end;
嗯,中学工作...有点。它不允许无人看管地释放我的线程。
如果将nestedTestProc
更改为下面的代码,则nestedTaskgets将在预期的时刻被销毁。不幸的是,这种解决方案显然不是“不可观察”的
procedure TfrmMain.MynestedTestProc(const aTask: IOmniTask);
var lTask:IOmniTaskControl;
begin
sleep(100);
SGOutputDebugStringFmt('%s.MyTestProc for %s','nestedTask');
try
lTask.Run;
lTask.WaitFor(2000);
finally
lTask:=nil;
end;
sleep(100);
end;
更新20201029 >>
完成主任务并且其关联的Monitor已被销毁时,通常会发生无效句柄(1400)错误。 因此,万一有一个“拥有的”监视器正在监视其他线程,“主”任务线程就不会死。
因此要进行检查,我更改了时间(使用sleep())以确保子任务在主任务完成之前 完成。 现在,无效句柄错误消失了,并且成功发布了COmniTaskMsg_Terminated消息。 但是仍然不处理子任务的ComniTaskMsg_Terminated。 (我希望MasterTask的线程可以处理此问题。) IMO有2个问题:
我还想知道这些关闭消息是否应该由应用程序主线程(似乎现在是这种情况)处理/处理,还是通过检查GTaskControlEventMonitorPool
中所有监视器的单独线程来处理/处理。友邦保险,相当复杂的东西:s ...
考虑到这一点,应由应用程序主线程(因此Monitor.ThreadID=MainThreadID
)创建的监视器应在主线程消息循环中处理其消息,而其他所有监视器可能都需要由单独的线程处理。 ..太令人困惑了!我将看看是否为此编写了单元测试,以证明我期望发生的事情。
问题
使用OmniThreadLibrary
,如何在线程内部使用未观察的线程,并避免所描述的内存泄漏?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。