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.