15

昔、私が Delphi でスレッドを扱い始めたとき、私はスレッドTThread.Resumeのコンストラクターの最後で呼び出すことによってスレッド自体を開始させていましたが、今でも次のように行っています。

constructor TMyThread.Create(const ASomeParam: String);
begin
  inherited Create(True);
  try
    FSomeParam:= ASomeParam;
    //Initialize some stuff here...
  finally
    Resume;
  end;
end;

それ以来、代わりResumeに使用することを支持して廃止されましたStart。ただし、Startスレッドの外部からのみ呼び出すことができ、コンストラクター内から呼び出すことはできません。

上記のように使用してスレッドを設計し続けていますが、非推奨であることはわかっていますが、スレッドの外部Resumeから呼び出す必要がないという理由だけです。Start呼び出す必要があるのは少し面倒です:

FMyThread := TMyThread.Create(SomeParamValue);
FMyThread.Start;

質問: この変更が行われた理由は何ですか? つまり、代わりResumeに使用することを望んでいるほど、使用することの何が間違っているのでしょうか?Start

EDIT Sedatの答えの後、これはコンストラクター内でスレッドが実際に実行を開始する時期に本当に依存していると思います。

4

1 に答える 1

13

簡潔で簡潔な答えは、TThreadクラスの作成者が、開発者がドキュメントを読んだり理解したりすることを信頼していなかったからです。:)

スレッドの一時停止と再開は、非常に限られた数のユース ケースでのみ正当な操作です。実際、その限られた数は本質的に「1」です: デバッガー

望ましくないもの

(控えめに言っても) 望ましくないと見なされる理由は、(たとえば) スレッドがミューテックスやセンパフォアなどの他の同期オブジェクトのロックを所有しているときにスレッドが中断されると、問題が発生する可能性があるためです。

これらの同期オブジェクトは、共有リソースにアクセスする他のスレッドに対してスレッドの安全な操作を確保するように特別に設計されているため、これらのメカニズムを中断したり干渉したりすると、問題が発生する可能性があります。

デバッガーには、驚くほど同様の理由から、これらのメカニズムに関係なく、スレッドを直接中断する機能が必要です。

たとえば、ブレークポイントに、スレッドでの暗黙的な (または明示的とさえ言える) "中断" 操作が含まれているとします。ブレークポイントに到達したときにデバッガーがスレッドを停止する場合、プロセス内の他のすべてのスレッドも一時停止する必要があります。それからする。

デバッガの強い腕

デバッガーは、適切で礼儀正しい同期オブジェクトとメカニズムを「注入」して、これらの他のスレッドが (ブレークポイントによって) 突然停止された他のスレッドと協調してサスペンドするように要求することはできません。デバッガーはスレッドを強化する以外に選択肢がありません。これがまさに Suspend/Resume API の目的です。

それらは、スレッドを停止する必要がある状況のためのものです。そして後で、「OK、今までやっていたことは何でも、何をしていたとしても、今は続けていい」と言うために。

正常に動作するスレッドは相互に正常に動作する

これは、正常に動作するスレッドが通常の操作で他のスレッドと対話する方法ではないことは明らかに明らかです(「通常の」操作の状態を維持し、あらゆる種類の問題を作成したくない場合)。これらの通常のケースでは、スレッドは他のスレッドが行っていることを非常にかけ、適切な同期技術を使用して他のスレッドと調整して干渉しないようにする必要があります。

そのような場合、スレッドを再開するための正当な使用例は、同様に 1 つの単一モードに縮小されます。つまり、すぐに実行するのではなく、他のスレッドの制御下で後で実行を開始するスレッドを作成して初期化したということです。

しかし、その新しいスレッド開始されたら、それ以降の他のスレッドとの同期は、強制的に中断するのではなく、適切な同期手法を使用して達成する必要があります。

開始と一時停止/再開

そのため、サスペンド/レジュームは汎用スレッド クラスには存在しないと判断され (デバッガーを実装する人々は Windows API を直接呼び出すことができます)、代わりに、より適切な "開始" メカニズムが提供されました。

このStartメカニズムは、非推奨となった Resume メソッドが以前に使用していたのとまったく同じ API を使用していますが、目的がまったく異なることが明らかになるはずです。

于 2016-03-15T04:06:29.747 に答える