【问题标题】:Migrating from Indy 9 to 10 with Delphi, TIdSchedulerOfThreadPool initialization使用 Delphi、TIdSchedulerOfThreadPool 初始化从 Indy 9 迁移到 10
【发布时间】:2013-01-25 03:20:58
【问题描述】:

我正在将 Delphi 应用程序从 Indy 9 更新到 Indy 10。

这很痛苦,因为显然发生了很多变化。

我被困在了一步。

这是旧代码(使用 Indy 9):

创建了一个线程池,池中的每个线程都被初始化然后启动。 各个线程创建一个 indy http 客户端(但在这里无关紧要)。

TUrlThread = class(TIdThread)

...  

var
  i: Integer;
begin
  // create the Pool and init it
  Pool            := TIdThreadMgrPool.Create(nil);
  Pool.PoolSize   := Options.RunningThreads;
  Pool.ThreadClass:= TUrlThread;

  // init threads and start them
  for i := 1 to Options.RunningThreads do
  begin
    with (Pool.GetThread as TUrlThread) do
    begin
      Index     := i;
      Controler := Self;
      Priority  := Options.Priority;
      Start;
    end;
  end;

TIdThreadMgrPool 类已随 Indy 10 消失。

我已经在寻找替代品,而 TIdSchedulerOfThreadPool 看起来像是赢家, 但我无法让它运行。

这是修改后的 (Indy 10) 代码:

TUrlThread = class(TIdThreadWithTask)

...

var
  i: Integer;
begin
  // create the Pool and init it
  Pool            := TIdSchedulerOfThreadPool.Create(nil);
  Pool.PoolSize   := Options.RunningThreads;
  Pool.ThreadClass:= TUrlThread;

  // init threads and start them
  for i := 1 to Options.RunningThreads do
  begin
    with (Pool.NewThread as TUrlThread) do
    begin
      Index     := i;
      Controler := Self;
      Priority  := Options.Priority;
      Start;
    end;
  end;

我在这里遇到访问冲突异常(这是 indy 代码):

procedure TIdTask.DoBeforeRun;
begin
  FBeforeRunDone := True;
  BeforeRun;
end;

FBeforeRunDone 为零。

【问题讨论】:

    标签: delphi indy indy10 indy-9


    【解决方案1】:

    TIdSchedulerOfThreadPool 是 Indy 10 的 TIdThreadMgrPool 的替代品,这是正确的。但是,您没有考虑到TIdScheduler 架构与TIdThreadMgr 架构有很大不同。

    在 Indy 10 中,TIdThreadWithTask 不会自行运行。顾名思义,TIdThreadWithTask 执行一个 Task,它是与线。您正在运行线程而不给它们执行任务,这就是您遇到崩溃的原因。为了手动调用Start(),您需要首先创建一个基于TIdTask 的对象并将其分配给TIdThreadWithTask.Task 属性。 TIdTCPServer 通过调用 TIdScheduler.AcquireYarn() 创建链接到 TIdThreadWithTask 对象的 TIdYarn 对象,然后创建 TIdContext 对象并将其传递给 TIdScheduler.StartYarn(),后者使用 TIdYarn 访问TIdThreadWithTask 分配其Task 属性,然后调用Start()

    但是,一切都没有丢失。在 Indy 9 和 10 中,您真的不应该一开始就手动调用 TIdThread.Start()TIdTCPServer 在接受新的客户端连接、从其ThreadMgr/Scheduler 获取线程并将客户端连接与线程相关联后为您处理。您可以根据需要初始化线程属性,而无需立即实际运行线程。这些属性将在线程第一次开始运行时生效。

    试试这个:

    TUrlThread = class(TIdThread)
    
    ...  
    
    var
      i: Integer;
    begin
      // create the Pool and init it
      Pool            := TIdThreadMgrPool.Create(nil);
      Pool.PoolSize   := Options.RunningThreads;
      Pool.ThreadClass:= TUrlThread;
      Pool.ThreadPriority := Options.Priority;
    
      // init threads and start them
      for i := 1 to Options.RunningThreads do
      begin
        with (Pool.GetThread as TUrlThread) do
        begin
          Index     := i;
          Controler := Self;
        end;
      end;
    

    .

    TUrlThread = class(TIdThreadWithTask)
    
    ...
    
    var
      i: Integer;
    begin
      // create the Pool and init it
      Pool            := TIdSchedulerOfThreadPool.Create(nil);
      Pool.PoolSize   := Options.RunningThreads;
      Pool.ThreadClass:= TUrlThread;
      Pool.ThreadPriority := Options.Priority;
    
      // init threads and start them
      for i := 1 to Options.RunningThreads do
      begin
        with (Pool.NewThread as TUrlThread) do
        begin
          Index     := i;
          Controler := Self;
        end;
      end;
    

    现在,话虽如此,最后一件事要注意。在 Indy 9 和 10 中,线程完成后可能不会放回池中,并且在初始化代码运行后新线程可能会添加到池中。 PoolSize 是保留在池中的最小线程数,而不是绝对计数。超过PoolSize 数量的客户端可以连接到服务器,它会在需要时为它们创建更多线程,从而绕过您的初始化代码。在这两个版本中,初始化线程的最佳位置是在 TUrlThread 构造函数中。将 Controler 指针存储在构造函数可以在需要时访问它的位置。而且给每个线程分配一个Index 是没有意义的,因为池中线程的顺序会随着时间动态变化。

    事实上,您的手动初始化代码实际上在两个版本中都是错误的方法,原因是另一个。 TIdThreadMgrPool.GetThread()TIdSchedulerOfThreadPool.NewThread() 都不会将新线程添加到池中。在 Indy 9 和 10 中,当线程停止运行并且有空间保存线程以供重用时,线程都会添加到池中,此外,仅当 TIdTCPServer 启动时,Indy 10 中才会将线程添加到池中。所以你实际上是在创建实际上没有做任何事情并且没有被池跟踪的线程。更有理由在两个版本中重新设计初始化代码,以便线程在正常条件下创建时自行初始化,而不是您侵入架构手动创建它们。

    【讨论】:

      猜你喜欢
      • 2014-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-02
      • 2020-09-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多