简体   繁体   中英

Delphi XE8 - Share variables between threads

I would like to know if it's possible to have this situation:

1) have a master thread with some variables.

2) this thread would have to create 2 sub-threads and this threads should be able to read the variables of the master thread.

3) I would like to create different master threads (with the sub-threads).

Is this even possible?

I tried this so far, but it does not work (Check "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.

Yes, it's possible to share variables among multiple threads. It's nearly automatic. If a variable's scope allows it to be referenced, then it will be accessible by whatever thread executes the code.

In the code provided, none of the threads have any way of referring to each other. In particular, the subthread has no reference to any instance of TMainThread , and so it won't be able to access the TestVar1 member of any such thread.

It is not correct to let the SubThread inherit from the MainThread and then expect to get the test value.

I think it is much better to let the SubThread hold a reference to your Main Thread, and then you end up with this:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM