如果我从主线程创建(挂起)线程:
with TMyThread.Create(True) do
begin
OnTerminate := ThreadTerminated;
FreeOnTerminate := False;
Start;
end;
Run Code Online (Sandbox Code Playgroud)
一旦完成,我该如何解放该实例?(即执行过程已完成执行 - 假设我已捕获异常).
这种破坏tthread对象链接的正确方法显示了一种方法(通过PostMessage过程),它工作正常并且有意义.但是,如果我创建线程并且我没有表单的句柄或我可以调用PostMessage过程的东西,该怎么办?例如,我在直接来自TObject的类中创建线程?
TMyClass = class
public
procedure DoSomething;
end;
TMyClass.DoSomething;
begin
with TMyThread.Create(True) do
begin
OnTerminate := ThreadTerminated;
FreeOnTerminate := False;
Start;
end;
end;
Run Code Online (Sandbox Code Playgroud)
所以,我想,如何在不访问表单句柄的情况下释放一个线程?
谢谢
假设在开始时创建具有某些表单且仅一个数据模块的应用程序.在这种情况DM1.OnCreate
下,TStringList
创建a以在运行时使用.我们知道,当应用程序被终止时,所有内容都将被销毁,内存将自动释放.释放某些东西可能需要一些时间,因此并不总是建议担心关机时的内存泄漏.例如,请参阅Barry Kelly的回答或Raymond Chen的这篇文章.
在那旁边,FastMM报告内存泄漏,如果我不添加TStringList.Free
到DM1.OnDestroy
.在搜索我真正担心的任何其他内存泄漏时,这会成为一个问题.
所以基本上我问是否/为什么/何时我应该释放将被应用程序或操作系统释放的对象实例(在这种特定情况下为Windows).有没有其他有效的案例不是在寻找内存泄漏时?
注意:在此特定情况下,不会创建或重新创建数据模块多次.除了那个之外,根本不会有任何内存泄漏.数据模块废料来源:
unit UDM1;
interface
uses SysUtils, Classes, ...;
type
TDM1 = class(TDataModule)
procedure DataModuleCreate(Sender: TObject);
procedure DataModuleDestroy(Sender: TObject);
procedure DoStuffWithStringList1(Sender: TObject);
private
internalStL: TStringList;
end;
var
DM1: TDM1;
implementation
procedure TDMInterfacePAFECF.DataModuleCreate(Sender: TObject);
begin
internalStL := TStringList.Create();
end;
procedure TDMInterfacePAFECF.DataModuleDestroy(Sender: TObject);
begin
internalStL.Free; //<-- IS THIS NECESSARY OR ADVISED?
end;
procedure DoStuffWithStringList(Sender: TObject);
begin
//Place some code using internalStL here...
end;
Run Code Online (Sandbox Code Playgroud) 首先,我仍然熟悉多线程,并且不太了解术语.我需要确保我做得对,因为这是一个敏感话题.
产品规格
我正在构建的是一个包含动态线程数的组件.这些线程中的每一个都被重用于执行许多请求.我可以在创建它时以及在执行它之前为线程提供所有必要的细节,以及提供事件处理程序.一旦它被执行,我几乎完成了一个请求,我提供了另一个请求.请求从另一个独立的后台线程被送入这些线程,后台线程不断处理请求队列.所以这个系统有两个列表:1)请求记录列表,2)线程指针列表.
我正在使用TThread
该类的后代(至少这是我熟悉的线程方法).我通过同步创建线程时分配的事件触发器从线程获得反馈.线程正在后台加载和保存数据,当它们完成后,它们会自行重置以准备处理下一个请求.
问题
现在的麻烦决定如何(通过组件的属性处理不断变化的允许线程的数量的情况下,当开始ActiveThreads: TActiveThreadRange
该TActiveThreadRange
= 1..20).因此,一次可以创建1到20个线程.但是,当我们说,使用这个组件的应用程序将此属性从5更改为3.此时,已经创建了5个线程,并且我不想强行释放该线程,如果它正好忙.我需要等到它完成后才能释放它.另一方面,如果属性从3更改为5,那么我需要创建2个新线程.我需要知道在这种情况下"跟踪"这些线程的正确方法.
可能性
以下是我可以想到的"跟踪"这些线程的一些可能方法......
TList
包含每个创建的线程 - 易于管理TList
包含每个创建的线程的包装器或后代 - 更易于管理,但需要更多工作array
包含每个创建的线程 - 这会比一个更好TList
吗?但回到我原来的问题 - 当ActiveThreads
属性减少时如何处理现有繁忙的线程?创建它们没有问题,但释放它们变得令人困惑.我通常制作自己解放的线程,但这是我第一次制作一个可以重复使用的线程.我只需要知道在不中断任务的情况下销毁这些线程的正确方法.
更新
根据反馈,我已经获得并开始实现OmniThreadLibrary(以及长期需要的FastMM).我也改变了我的方法 - 我可以创建这些线程进程而无需管理它们,也没有其他线程来处理队列...
function NewProcess(const Request: TProcessRequest): TProcessInfo;
TProcessRequest
是一个记录,其中包含要执行的操作的规范(文件名,选项等)TProcessInfo
是一个传回一些状态信息的记录.另一个更新
我实际上已经恢复使用了一个TThread
,因为OTL非常不舒服.我喜欢在自己的课堂上把东西包裹起来.
假设我有一个在应用程序终止时仍在运行的线程
(此线程无法终止,因为它等待Windows api调用返回,并且可能很长...)
如果应用程序关闭,线程会发生什么?
它可以引发异常(我在Delphi下)吗?