使用: Delphi XE2、Windows VCL フォーム アプリケーション
実行中の TThread はメイン VCL スレッドの変数の値を変更できますか?
TForm クラスのフィールドとして宣言されている Integer を更新する必要があります。これは、オーバーロードされた (そして再導入された) Create コンストラクター メソッドの var 変数として TThread に渡されます。
これにフォールバックはありますか?
はい、スレッドは変数を変更できます。変数はスレッドに属しません。変数はフォーム オブジェクトまたはスレッド オブジェクトに属することができますが、スレッド オブジェクト (つまり、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;
いずれの場合も、複数のスレッドによるデータへの同時アクセスの制御について、通常の予防措置を講じる必要があります。要するに、両方のスレッドがデータにアクセスできるということです。