Delphi XE8 - 在线程之间共享变量
Delphi XE8 - Share variables between threads
我想知道有没有可能出现这种情况:
1) 有一个带有一些变量的主线程。
2) 这个线程必须创建2个子线程并且这个线程应该能够读取主线程的变量。
3) 我想创建不同的主线程(与子线程)。
这可能吗?
到目前为止我试过了,但它不起作用(检查 "procedure TSubThread.Execute;" ):
unit uMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
type
TMainThread = class(TThread)
private
protected
procedure Execute; override;
public
TestVar1: integer;
end;
TSubThread = class(TMainThread)
private
protected
procedure Execute; override;
public
end;
TfMain = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
function RunThread(trTestVar1: integer): TMainThread;
procedure ThreadTerminated(Sender: TObject);
function RunSubThread: TSubThread;
procedure SubThreadTerminated(Sender: TObject);
public
{ Public declarations }
end;
var
fMain: TfMain;
implementation
{$R *.dfm}
////////////////////////////////////////////////////////////////////////////////
// MAINTHREAD
////////////////////////////////////////////////////////////////////////////////
function TfMain.RunThread(trTestVar1: integer): TMainThread;
var CalcThread : TMainThread;
begin
CalcThread := TMainThread.Create(true);
CalcThread.TestVar1 := trTestVar1;
CalcThread.FreeOnTerminate := true;
CalcThread.OnTerminate := ThreadTerminated;
CalcThread.Start;
Result := CalcThread;
// Here I start the SUB-THREAD
RunSubThread;
end;
procedure TfMain.ThreadTerminated(Sender: TObject);
begin
//
end;
procedure TMainThread.Execute;
begin
inherited;
end;
////////////////////////////////////////////////////////////////////////////////
// SUBTHREAD
////////////////////////////////////////////////////////////////////////////////
function TfMain.RunSubThread: TSubThread;
var SubThread : TSubThread;
begin
SubThread := TSubThread.Create(true);
SubThread.FreeOnTerminate := true;
SubThread.OnTerminate := SubThreadTerminated;
SubThread.Start;
Result := SubThread;
end;
procedure TfMain.SubThreadTerminated(Sender: TObject);
begin
//
end;
procedure TSubThread.Execute;
begin
inherited;
// Here the value of TestVar1 is always 0
end;
////////////////////////////////////////////////////////////////////////////////
// MAIN THREAD
////////////////////////////////////////////////////////////////////////////////
procedure TfMain.FormCreate(Sender: TObject);
begin
// I start the first "Main Thread"
RunThread(1);
// I start the second "Main Thread"
RunThread(2);
end;
end.
是的,可以在多个线程之间共享变量。它几乎是自动的。如果变量的范围允许引用它,那么执行代码的任何线程都可以访问它。
在提供的代码中,none 个线程可以通过任何方式相互引用。特别是,子线程没有引用 TMainThread
的任何实例,因此它无法访问任何此类线程的 TestVar1
成员。
让SubThread继承MainThread然后期望得到测试值是不正确的
我认为让 SubThread 持有对主线程的引用要好得多,然后你会得到这样的结果:
unit uMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
type
TMainThread = class(TThread)
private
protected
procedure Execute; override;
public
TestVar1: integer;
end;
TSubThread = class(TThread)
private
FMainThread : TMainThread;
protected
procedure Execute; override;
public
end;
TfMain = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
function RunThread(trTestVar1: integer): TMainThread;
procedure ThreadTerminated(Sender: TObject);
function RunSubThread(MainThread : TMainThread): TSubThread;
procedure SubThreadTerminated(Sender: TObject);
public
{ Public declarations }
end;
var
fMain: TfMain;
implementation
{$R *.dfm}
////////////////////////////////////////////////////////////////////////////////
// MAINTHREAD
////////////////////////////////////////////////////////////////////////////////
function TfMain.RunThread(trTestVar1: integer): TMainThread;
var CalcThread : TMainThread;
begin
CalcThread := TMainThread.Create(true);
CalcThread.TestVar1 := trTestVar1;
CalcThread.FreeOnTerminate := true;
CalcThread.OnTerminate := ThreadTerminated;
CalcThread.Start;
Result := CalcThread;
// Here I start the SUB-THREAD
RunSubThread(CalcThread);
end;
procedure TfMain.ThreadTerminated(Sender: TObject);
begin
//
end;
procedure TMainThread.Execute;
begin
inherited;
end;
////////////////////////////////////////////////////////////////////////////////
// SUBTHREAD
////////////////////////////////////////////////////////////////////////////////
function TfMain.RunSubThread(MainThread : TMainThread): TSubThread;
var SubThread : TSubThread;
begin
SubThread := TSubThread.Create(true);
SubThread.FreeOnTerminate := true;
SubThread.FMainThread := MainThread;
SubThread.OnTerminate := SubThreadTerminated;
SubThread.Start;
Result := SubThread;
end;
procedure TfMain.SubThreadTerminated(Sender: TObject);
begin
//
end;
procedure TSubThread.Execute;
var
VarCopy : Integer;
begin
inherited;
VarCopy := self.FMainThread.TestVar1;
// Here the value of TestVar1 is always 0
end;
////////////////////////////////////////////////////////////////////////////////
// MAIN THREAD
////////////////////////////////////////////////////////////////////////////////
procedure TfMain.FormCreate(Sender: TObject);
begin
// I start the first "Main Thread"
RunThread(1);
// I start the second "Main Thread"
RunThread(2);
end;
end.
我想知道有没有可能出现这种情况:
1) 有一个带有一些变量的主线程。
2) 这个线程必须创建2个子线程并且这个线程应该能够读取主线程的变量。
3) 我想创建不同的主线程(与子线程)。
这可能吗?
到目前为止我试过了,但它不起作用(检查 "procedure TSubThread.Execute;" ):
unit uMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
type
TMainThread = class(TThread)
private
protected
procedure Execute; override;
public
TestVar1: integer;
end;
TSubThread = class(TMainThread)
private
protected
procedure Execute; override;
public
end;
TfMain = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
function RunThread(trTestVar1: integer): TMainThread;
procedure ThreadTerminated(Sender: TObject);
function RunSubThread: TSubThread;
procedure SubThreadTerminated(Sender: TObject);
public
{ Public declarations }
end;
var
fMain: TfMain;
implementation
{$R *.dfm}
////////////////////////////////////////////////////////////////////////////////
// MAINTHREAD
////////////////////////////////////////////////////////////////////////////////
function TfMain.RunThread(trTestVar1: integer): TMainThread;
var CalcThread : TMainThread;
begin
CalcThread := TMainThread.Create(true);
CalcThread.TestVar1 := trTestVar1;
CalcThread.FreeOnTerminate := true;
CalcThread.OnTerminate := ThreadTerminated;
CalcThread.Start;
Result := CalcThread;
// Here I start the SUB-THREAD
RunSubThread;
end;
procedure TfMain.ThreadTerminated(Sender: TObject);
begin
//
end;
procedure TMainThread.Execute;
begin
inherited;
end;
////////////////////////////////////////////////////////////////////////////////
// SUBTHREAD
////////////////////////////////////////////////////////////////////////////////
function TfMain.RunSubThread: TSubThread;
var SubThread : TSubThread;
begin
SubThread := TSubThread.Create(true);
SubThread.FreeOnTerminate := true;
SubThread.OnTerminate := SubThreadTerminated;
SubThread.Start;
Result := SubThread;
end;
procedure TfMain.SubThreadTerminated(Sender: TObject);
begin
//
end;
procedure TSubThread.Execute;
begin
inherited;
// Here the value of TestVar1 is always 0
end;
////////////////////////////////////////////////////////////////////////////////
// MAIN THREAD
////////////////////////////////////////////////////////////////////////////////
procedure TfMain.FormCreate(Sender: TObject);
begin
// I start the first "Main Thread"
RunThread(1);
// I start the second "Main Thread"
RunThread(2);
end;
end.
是的,可以在多个线程之间共享变量。它几乎是自动的。如果变量的范围允许引用它,那么执行代码的任何线程都可以访问它。
在提供的代码中,none 个线程可以通过任何方式相互引用。特别是,子线程没有引用 TMainThread
的任何实例,因此它无法访问任何此类线程的 TestVar1
成员。
让SubThread继承MainThread然后期望得到测试值是不正确的
我认为让 SubThread 持有对主线程的引用要好得多,然后你会得到这样的结果:
unit uMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
type
TMainThread = class(TThread)
private
protected
procedure Execute; override;
public
TestVar1: integer;
end;
TSubThread = class(TThread)
private
FMainThread : TMainThread;
protected
procedure Execute; override;
public
end;
TfMain = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
function RunThread(trTestVar1: integer): TMainThread;
procedure ThreadTerminated(Sender: TObject);
function RunSubThread(MainThread : TMainThread): TSubThread;
procedure SubThreadTerminated(Sender: TObject);
public
{ Public declarations }
end;
var
fMain: TfMain;
implementation
{$R *.dfm}
////////////////////////////////////////////////////////////////////////////////
// MAINTHREAD
////////////////////////////////////////////////////////////////////////////////
function TfMain.RunThread(trTestVar1: integer): TMainThread;
var CalcThread : TMainThread;
begin
CalcThread := TMainThread.Create(true);
CalcThread.TestVar1 := trTestVar1;
CalcThread.FreeOnTerminate := true;
CalcThread.OnTerminate := ThreadTerminated;
CalcThread.Start;
Result := CalcThread;
// Here I start the SUB-THREAD
RunSubThread(CalcThread);
end;
procedure TfMain.ThreadTerminated(Sender: TObject);
begin
//
end;
procedure TMainThread.Execute;
begin
inherited;
end;
////////////////////////////////////////////////////////////////////////////////
// SUBTHREAD
////////////////////////////////////////////////////////////////////////////////
function TfMain.RunSubThread(MainThread : TMainThread): TSubThread;
var SubThread : TSubThread;
begin
SubThread := TSubThread.Create(true);
SubThread.FreeOnTerminate := true;
SubThread.FMainThread := MainThread;
SubThread.OnTerminate := SubThreadTerminated;
SubThread.Start;
Result := SubThread;
end;
procedure TfMain.SubThreadTerminated(Sender: TObject);
begin
//
end;
procedure TSubThread.Execute;
var
VarCopy : Integer;
begin
inherited;
VarCopy := self.FMainThread.TestVar1;
// Here the value of TestVar1 is always 0
end;
////////////////////////////////////////////////////////////////////////////////
// MAIN THREAD
////////////////////////////////////////////////////////////////////////////////
procedure TfMain.FormCreate(Sender: TObject);
begin
// I start the first "Main Thread"
RunThread(1);
// I start the second "Main Thread"
RunThread(2);
end;
end.