1

使用: Delphi XE2、Windows VCL フォーム アプリケーション

実行中の TThread はメイン VCL スレッドの変数の値を変更できますか?

TForm クラスのフィールドとして宣言されている Integer を更新する必要があります。これは、オーバーロードされた (そして再導入された) Create コンストラクター メソッドの var 変数として TThread に渡されます。

これにフォールバックはありますか?

4

1 に答える 1

10

はい、スレッドは変数を変更できます。変数はスレッドに属しません。変数はフォーム オブジェクトまたはスレッド オブジェクトに属することができますが、スレッド オブジェクト (つまり、TThreadまたはその子孫のインスタンス) は OS 実行スレッドとは異なります。

オブジェクトには、複数のスレッドで実行されるコードを含めることができます。メソッドTThread.Createは、それを呼び出すスレッド (多くの場合、メイン スレッド) のコンテキストで実行されます。一方、このExecuteメソッドは、作成された OS スレッドのコンテキストで実行されます。しかし、明らかに、両方のメソッドがTThreadオブジェクトのフィールドにアクセスできるため、2 つの OS スレッドが同じ変数にアクセスできるかどうかという疑問に答えます。

ただし、説明した方法でフォーム変数にアクセスするのは困難です。これを var パラメーターとしてコンストラクターに渡すと、コンストラクターはそれを変更できますが、で述べたように、コンストラクターは新しい OS スレッドのコンテキストでは実行されません。新しいスレッドがその変数にアクセスできるようにするには、参照渡しではなく、変数へのポインターを格納する必要があります。例えば:

type
  TSteveThread = class(TThread)
  private
    FVariable: PInteger;
  protected
    procedure Execute; override;
  public
    constructor Create(Variable: PInteger);
  end;

constructor TSteveThread.Create;
begin
  inherited Create(False);
  FVariable := Variable;
end;

procedure TSteveThread.Execute;
begin
  // Access FVariable^ here.
end;

次のように作成します。

procedure TSteveForm.ButtonClick;
begin
  TSteveThread.Create(@Self.Variable);
end;

別の方法として、代わりにフォームへの参照を渡し、その参照を介してフォームのフィールドにアクセスします。例えば:

type
  TSteveThread = class(TThread)
  private
    FForm: TSteveForm;
  protected
    procedure Execute; override;
  public
    constructor Create(Form: TSteveForm);
  end;

constructor TSteveThread.Create;
begin
  inherited Create(False);
  FForm := Form;
end;

procedure TSteveThread.Execute;
begin
  // Access FForm.Variable here.
end;

次のように作成します。

procedure TSteveForm.ButtonClick;
begin
  TSteveThread.Create(Self);
end;

いずれの場合も、複数のスレッドによるデータへの同時アクセスの制御について、通常の予防措置を講じる必要があります。要するに、両方のスレッドがデータにアクセスできるということです

于 2015-02-04T05:26:13.037 に答える