相关疑难解决方法(0)

何时手动释放线程

如果我从主线程创建(挂起)线程:

  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)

所以,我想,如何在不访问表单句柄的情况下释放一个线程?

谢谢

delphi delphi-xe2

8
推荐指数
1
解决办法
5492
查看次数

除了寻找内存泄漏之外,还有其他情况我应该在销毁应用程序时释放所有对象吗?

假设在开始时创建具有某些表单且仅一个数据模块的应用程序.在这种情况DM1.OnCreate下,TStringList创建a以在运行时使用.我们知道,当应用程序被终止时,所有内容都将被销毁,内存将自动释放.释放某些东西可能需要一些时间,因此并不总是建议担心关机时的内存泄漏.例如,请参阅Barry Kelly的回答或Raymond Chen的这篇文章.

在那旁边,FastMM报告内存泄漏,如果我不添加TStringList.FreeDM1.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)

delphi free memory-leaks fastmm

8
推荐指数
3
解决办法
900
查看次数

管理动态线程数

首先,我仍然熟悉多线程,并且不太了解术语.我需要确保我做得对,因为这是一个敏感话题.

产品规格

我正在构建的是一个包含动态线程数的组件.这些线程中的每一个都被重用于执行许多请求.我可以在创建它时以及在执行它之前为线程提供所有必要的细节,以及提供事件处理程序.一旦它被执行,我几乎完成了一个请求,我提供了另一个请求.请求从另一个独立的后台线程被送入这些线程,后台线程不断处理请求队列.所以这个系统有两个列表:1)请求记录列表,2)线程指针列表.

我正在使用TThread该类的后代(至少这是我熟悉的线程方法).我通过同步创建线程时分配的事件触发器从线程获得反馈.线程正在后台加载和保存数据,当它们完成后,它们会自行重置以准备处理下一个请求.

问题

现在的麻烦决定如何(通过组件的属性处理不断变化的允许线程的数量的情况下,当开始ActiveThreads: TActiveThreadRangeTActiveThreadRange= 1..20).因此,一次可以创建1到20个线程.但是,当我们说,使用这个组件的应用程序将此属性从5更改为3.此时,已经创建了5个线程,并且我不想强行释放该线程,如果它正好忙.我需要等到它完成后才能释放它.另一方面,如果属性从3更改为5,那么我需要创建2个新线程.我需要知道在这种情况下"跟踪"这些线程的正确方法.

可能性

以下是我可以想到的"跟踪"这些线程的一些可能方法......

  • 保持TList包含每个创建的线程 - 易于管理
  • 创建一个TList包含每个创建的线程的包装器或后代 - 更易于管理,但需要更多工作
  • 保持array包含每个创建的线程 - 这会比一个更好TList吗?
  • 创建一个包含每个创建的线程的数组包装器

但回到我原来的问题 - 当ActiveThreads属性减少时如何处理现有繁忙的线程?创建它们没有问题,但释放它们变得令人困惑.我通常制作自己解放的线程,但这是我第一次制作一个可以重复使用的线程.我只需要知道在不中断任务的情况下销毁这些线程的正确方法.

更新

根据反馈,我已经获得并开始实现OmniThreadLibrary(以及长期需要的FastMM).我也改变了我的方法 - 我可以创建这些线程进程而无需管理它们,也没有其他线程来处理队列...

  • 1个生成新进程的主方法
    • function NewProcess(const Request: TProcessRequest): TProcessInfo;
    • TProcessRequest 是一个记录,其中包含要执行的操作的规范(文件名,选项等)
    • TProcessInfo 是一个传回一些状态信息的记录.
  • 在创建新流程时,为事件"完成"事件处理事件处理程序.当组件收到此消息时,它将检查队列.
    • 如果命令排队,它会将活动进程限制与当前进程计数进行比较
    • >如果超出限制,只需停止,下一个完成的过程将执行相同的检查
    • >如果在限制范围内,启动另一个新流程(确保之前的流程完成后)
    • 如果没有命令排队,那么就停止
  • 每个进程在完成任务后都可以自行死亡(没有保持活动的线程)
  • 我不必担心另一个计时器或线程不断循环
    • 相反,每个进程都会破坏其自身并在执行此操作之前检查新请求

另一个更新

我实际上已经恢复使用了一个TThread,因为OTL非常不舒服.我喜欢在自己的课堂上把东西包裹起来.

delphi queue multithreading list delphi-xe2

7
推荐指数
2
解决办法
2373
查看次数

在Delphi下终止应用程序时,线程未终止

假设我有一个在应用程序终止时仍在运行的线程

(此线程无法终止,因为它等待Windows api调用返回,并且可能很长...)

如果应用程序关闭,线程会发生什么?

它可以引发异常(我在Delphi下)吗?

windows delphi multithreading

2
推荐指数
1
解决办法
1780
查看次数