Delphi - TThread可以在主VCL线程中更改变量的值吗?

时间:2015-02-04 04:54:57

标签: delphi tthread

使用:Delphi XE2,Windows VCL Forms应用程序

TThread在执行期间是否可以更改主VCL线程中变量的值?

需要更新一个被声明为TForm类字段的Integer。它将作为重载(并重新引入)Create构造函数方法中的var变量传递给TThread。

这有没有后退?

1 个答案:

答案 0 :(得分:10)

是的,线程可以修改变量。变量不属于属于线程。变量可以属于表单或线程对象,但是线程对象(即TThread或其后代的实例)与OS执行线程不同。

对象可以包含在多个线程中运行的代码。您的TThread.Create方法在调用它的线程的上下文中运行,这通常是您的主线程。另一方面,Execute方法在创建的OS线程的上下文中运行。但显然,这两种方法都可以访问TThread对象的字段,因此可以回答两个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;

在任何一种情况下,您都需要采取通常的预防措施来控制多个线程同时访问数据。底线是两个线程可以访问数据。