使用:Delphi XE2,Windows VCL Forms应用程序
TThread在执行期间是否可以更改主VCL线程中变量的值?
需要更新一个被声明为TForm类字段的Integer。它将作为重载(并重新引入)Create构造函数方法中的var变量传递给TThread。
这有没有后退?
答案 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;
在任何一种情况下,您都需要采取通常的预防措施来控制多个线程同时访问数据。底线是两个线程可以访问数据。