Delphi XE8 - 在线程之间共享变量

时间:2015-10-30 15:45:32

标签: multithreading delphi delphi-xe8

我想知道是否可能出现这种情况:

1)有一个包含一些变量的主线程。

2)这个线程必须创建2个子线程,这个线程应该能够读取主线程的变量。

3)我想创建不同的主线程(使用子线程)。

这甚至可能吗?

我到目前为止尝试了这个,但它不起作用(检查"过程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.

2 个答案:

答案 0 :(得分:0)

是的,可以在多个线程之间共享变量。它几乎是自动的。如果变量的作用域允许它被引用,则任何执行代码的线程都可以访问它。

在提供的代码中,没有任何线程可以互相引用。特别是,子线程没有引用TMainThread的任何实例,因此它无法访问任何此类线程的TestVar1成员。

答案 1 :(得分:0)

让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.