繁体   English   中英

我如何在delphi项目中执行两个线程

[英]how i can execute two threads in delphi project

我的项目包含执行不同任务的两个过程,并且我在计时器中执行每个线程。

我的问题是……当我运行项目时,计时器启动。 线程无法正常工作。

为什么?

而且,我可以在同一项目中使用两个或多个线程吗?

注意:我真的想使用线程,我需要一个线程解决方案。

这是我的无线程代码。

procedure TForm1.Timer1Timer(Sender: TObject);
var
i : integer;
begin
for i := 0 to 50 do
  begin
  Memo1.Lines.Add(IntToStr(i));
  sleep(500);
  end;
end;

procedure TForm1.Timer2Timer(Sender: TObject);
var
k : integer;
begin
for k := 0 to 50 do
  begin
  Memo2.Lines.Add(IntToStr(k));
  sleep(500);
  end;
end;

end.

带螺纹:

type
TThread_Timer2 = class(TThread)
protected
  procedure Execute; override;
end;

type
TThread_Timer3 = class(TThread)
protected
  procedure Execute; override;
end;

procedure TThread_Timer2.Execute;
var
i : integer;
begin
for i := 0 to 50 do
  begin
  Memo1.Lines.Add(IntToStr(i));
  sleep(500);
  end;
end;

procedure TThread_Timer3.Execute;
var
k : integer;
begin
for k := 0 to 50 do
  begin
  Memo2.Lines.Add(IntToStr(k));
  sleep(500);
  end;
end;

procedure TForm1.Timer2Timer(Sender: TObject);
var
thd : TThread_Timer2;
begin
  thd := TThread_Timer2.Create(true);
  try
    thd.FreeOnTerminate := true;
    thd.Priority := tpHighest;
  finally
    thd.Resume;
  end;
end;


procedure TForm1.Timer3Timer(Sender: TObject);
var
trhd : TThread_Timer3;
begin
  trhd := TThread_Timer3.Create(true);
  try
    trhd.FreeOnTerminate := true;
    trhd.Priority := tpHighest;
  finally
    trhd.Resume;
  end;

end;

您可以根据需要使用任意多个线程。 但是,您必须遵守VCL的规则。 具体来说,您只能从主线程访问VCL组件。 您的代码违反了该规则。

每当您要从线程访问VCL组件时,请使用TThread.SynchronizeTThread.Queue方法在主线程上执行代码。

查看您的代码,如果您真的想在每次触发计时器时创建一个新线程,我都会感到惊讶。 那真的是你打算做的吗? 并且在计时器过程中使用try/finally final充其量是可疑的。 如果引发异常,您是否真的要启动线程。 编译器应告诉您Resume方法已被弃用,而应使用Start代替。 您是否启用了编译器提示和警告? 您几乎可以肯定不希望修改线程优先级。 如果使用不当,可能会导致各种问题,例如此处的情况。


综上所述,如果您愿意并可以避免使用任何线程,则可以使用计时器完美地编写代码。 您需要声明几个每次触发计时器过程时都会增加的计数器。 例如:

type
  TForm1 = class(TForm)
  ....
  private
    FCounter1: Integer;
  .... 
  end;

然后,当您要开始计数时,请初始化计数器并启动计时器:

 FCounter1 := 0;
 Timer1.Enabled := True;

每当计时器触发您的增量计数器时。 当计数器达到最大值时,您将其停止。

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Memo1.Lines.Add(IntToStr(FCounter1));
  inc(FCounter1);
  if FCounter1 > 50 then
    Timer1.Enabled := False;
end;

您的代码,经过纠正后只能在主线程中执行UI操作。 它为我工作:

TThread_Timer2 = class(TThread)
private
  FVar: Integer;

  procedure UpdateMemo;
protected
  procedure Execute; override;
end;

TThread_Timer3 = class(TThread)
private
  FVar: Integer;

  procedure UpdateMemo;
protected
  procedure Execute; override;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
thd : TThread_Timer2;
begin
  thd := TThread_Timer2.Create(true);
  try
    thd.FreeOnTerminate := true;
    thd.Priority := tpHighest;
  finally
    thd.Resume;
  end;
end;

procedure TThread_Timer2.Execute;
var
i : integer;
begin
for i := 0 to 50 do
  begin
  FVar := i;
  Synchronize(UpdateMemo);
  sleep(500);
  end;
end;

procedure TThread_Timer3.Execute;
var
k : integer;
begin
for k := 0 to 50 do
  begin
  FVar := k;
  Synchronize(UpdateMemo);
  sleep(500);
  end;
end;

procedure TForm1.Timer2Timer(Sender: TObject);
var
trhd : TThread_Timer3;
begin
  trhd := TThread_Timer3.Create(true);
  try
    trhd.FreeOnTerminate := true;
    trhd.Priority := tpHighest;
  finally
    trhd.Resume;
  end;

end;

procedure TThread_Timer2.UpdateMemo;
begin
  Form1.Memo1.Lines.Add(IntToStr(FVar));
end;

procedure TThread_Timer3.UpdateMemo;
begin
  Form1.Memo2.Lines.Add(IntToStr(FVar));
end;

我没有在您的代码中进行任何其他更改,但请仔细阅读David的答案。 有一些注意事项。

亚当,

如果您使用Parallel库,会更容易。 您的初始过程将如下所示:

proceedure TForm1.Timer1Timer(Sender: TObject);`
begin
  TTask.Run(procedure
            var 
              i: integer;
            begin
              for i:=0 to 50 do
              begin
                TThread.Synchronize(TThread.CurrentThread,
                     procedure 
                     begin
                       Memo1.Lines.Add(i.ToString);
                       Sleep(500);
                     end);
              end;
            end);
end;

根据@GabrielF的回复,我添加了一个ttimer并制作了完整的代码来复制和粘贴:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    procedure Timer1Timer(Sender: TObject);
    procedure Timer2Timer(Sender: TObject);
  public
    { Public declarations }
  end;

TThread_Timer2 = class(TThread)
private
  FVar: Integer;

  procedure UpdateMemo;
protected
  procedure Execute; override;
end;

TThread_Timer3 = class(TThread)
private
  FVar: Integer;

  procedure UpdateMemo;
protected
  procedure Execute; override;
end;


var
  Form1: TForm1;
  Memo1:TMemo;
  Memo2:TMemo;
  Timer: TTimer;

implementation

{$R *.dfm}


procedure TForm1.Timer1Timer(Sender: TObject);
var
thd : TThread_Timer2;
begin
  thd := TThread_Timer2.Create(true);
  try
    thd.FreeOnTerminate := true;
    thd.Priority := tpHighest;
  finally
    thd.Resume;
  end;
end;

procedure TThread_Timer2.Execute;
var
i : integer;
begin
for i := 0 to 10 do
  begin
  FVar := i;
  Synchronize(UpdateMemo);
  sleep(1000);
  end;
end;

procedure TThread_Timer3.Execute;
var
k : integer;
begin
for k := 0 to 10 do
  begin
  FVar := k;
  Synchronize(UpdateMemo);
  sleep(1000);
  end;
end;

procedure TForm1.Timer2Timer(Sender: TObject);
var
trhd : TThread_Timer3;
begin
  trhd := TThread_Timer3.Create(true);
  try
    trhd.FreeOnTerminate := true;
    trhd.Priority := tpHighest;
  finally
    trhd.Resume;
  end;

end;

procedure TThread_Timer2.UpdateMemo;
begin
  Memo1.Lines.Add(IntToStr(FVar));
end;

procedure TThread_Timer3.UpdateMemo;
begin
  Memo2.Lines.Add(IntToStr(FVar));
end;


procedure TForm1.FormCreate(Sender: TObject);
var bt1,bt2: TButton;
begin
  Form1.Width:=440;
  Form1.Height:=500;
  //
  Memo1 := TMemo.Create(nil);
  Memo1.Width := 200;
  Memo1.Height := 400;
  Memo1.Top := 30;
  Memo1.Parent := Form1;
  //
  Memo2 := TMemo.Create(nil);
  Memo2.Width := 200;
  Memo2.Height := 400;
  Memo2.Top := 30;
  Memo2.Left := 210;
  Memo2.Parent := Form1;
  //
  Timer := TTimer.Create(nil);
  Timer.Interval := 10000;
  Timer.OnTimer := Timer2Timer;
  Timer.Enabled := true;
  //
  bt1 := TButton.Create(nil);
  bt1.Width := 200;
  bt1.OnClick := Timer1Timer;
  bt1.Caption := 'Create thread Memo1';
  bt1.Parent := Form1;
  //
  bt2 := TButton.Create(nil);
  bt2.Left:=210;
  bt2.Width := 200;
  bt2.OnClick := Timer2Timer;
  bt2.Caption := 'Create thread Memo2';
  bt2.Parent := Form1;

end;

end.

也许它可以帮助某人。 我在Delphi7上编写并测试了它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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