5

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 は nil です。

4

1 に答える 1

7

あなたは正しいです、それTIdSchedulerOfThreadPoolはインディ10の代わりですTIdThreadMgrPool。ただし、考慮していないのは、TIdSchedulerアーキテクチャがアーキテクチャとはかなり異なるということTIdThreadMgrです。

Indy 10では、単独でTIdThreadWithTaskは動作しません。その名前が示すように、スレッドに関連付けられる派生オブジェクト(Indy 10の代わりのオブジェクトなど)であるタスクTIdThreadWithTaskを実行します。実行するタスクを与えずにスレッドを実行しているため、クラッシュが発生しています。手動で呼び出すには、最初にベースのオブジェクトを作成してプロパティに割り当てる必要があります。 オブジェクトにリンクされているオブジェクトを作成するために呼び出すことによってそれを処理し、次にオブジェクトを作成してに渡します。TIdTaskTIdContextTIdPeerThreadStart()TIdTaskTIdThreadWithTask.TaskTIdTCPServerTIdScheduler.AcquireYarn()TIdYarnTIdThreadWithTaskTIdContextTIdScheduler.StartYarn()TIdYarnTIdThreadWithTaskTaskStart()その上に。

ただし、すべてが失われるわけではありません。TIdThread.Start()Indy 9と10の両方で、最初から手動で 呼び出すべきではありません。新しいクライアント接続を受け入れ、その/TIdTCPServerからスレッドを取得し、クライアント接続をスレッドに関連付けた後、それを処理します。実際にスレッドをすぐに実行しなくても、必要に応じてスレッドのプロパティを初期化できます。プロパティは、スレッドが後で実行を開始したときに有効になります。ThreadMgrScheduler

これを試して:

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;

さて、そうは言っても、最後に注意すべきことが1つあります。Indy 9と10の両方で、終了時にスレッドがプールに戻されない可能性があり、初期化コードの実行後に新しいスレッドがプールに追加される可能性があります。これPoolSizeは、プールに保持するスレッドの最小数であり、絶対数ではありません。PoolSize多数のクライアントがサーバーに接続でき、サーバーは必要なときにそれらのスレッドをより多く作成できるため、初期化コードをバイパスします。どちらのバージョンでも、スレッドを初期化するのに最適な場所はTUrlThreadコンストラクターです。Controlerコンストラクターが必要なときにポインターに到達できる場所にポインターを保管します。そして、を割り当てることは意味がありませんIndexプール内のスレッドの順序は時間の経過とともに動的に変化するため、各スレッドに割り当てられます。

実際、手動の初期化コードは、別の理由で両方のバージョンで実際には間違ったアプローチです。両方とも、新しいスレッドをプールにまったく追加しませんTIdThreadMgrPool.GetThread()TIdSchedulerOfThreadPool.NewThread()スレッドは、スレッドの実行が停止し、再利用のためにスレッドを保存する余地がある場合に、Indy 9と10の両方でプールに追加されます。さらに、Indy 10では、TIdTCPServer起動時にのみ追加されます。したがって、実際には何も実行しておらず、プールによって追跡されていないスレッドを実際に作成しています。両方のバージョンで初期化コードを再設計して、アーキテクチャをハッキングして手動で作成するのではなく、スレッドが通常の条件下で作成されたときにスレッドが初期化されるようにする理由はなおさらです。

于 2013-01-25T09:42:39.720 に答える