【问题标题】:how i can execute two threads in delphi project我如何在delphi项目中执行两个线程
【发布时间】:2016-03-16 15:10:47
【问题描述】:

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

我的问题是......当我运行项目时,计时器开始了。 线程不能正常工作。

为什么?

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

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

这是我的无线程代码。

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;

【问题讨论】:

  • Idk 如果这是您的问题的原因(您应该详细说明“线程无法正常工作”),但您的代码中肯定存在问题:您正在从工作线程更新 UI。 UI 操作必须发生在主线程上。请参阅Synchronize 了解更多信息。

标签: multithreading delphi delphi-xe7


【解决方案1】:

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

当你想从你的线程访问一个 VCL 组件时,使用TThread.SynchronizeTThread.Queue 方法在主线程上执行代码。

查看您的代码,如果您真的想在每次触发计时器时创建一个新线程,我会感到惊讶。这真的是你打算做的吗?在定时器程序中使用try/finally 充其量是可疑的。如果引发异常,您是否真的要启动线程。编译器应该会告诉您 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;

【讨论】:

  • David,您的替代代码不会重现相同的结果:可以在最后一个完成之前使用计时器创建新的工作线程,并且您可以让它们同时运行。
  • @GabrielF 正如我所提到的,我怀疑这种行为是不希望的,不应该被复制。问题中基于计时器的代码的行为方式并非如此。
  • 哦,抱歉,我在编辑中迷路了。但是有这样的:“注意:我真的很想使用线程,我需要一个带有线程的解决方案。”。我真的相信这段代码和问题的目的只是为了学习一些关于使用线程的知识。
  • @GabrielF 也许吧。但同样合理的是,考虑到问题中代码的所有问题,asker 认为线程是解决方案,因为 asker 不了解如何在没有线程的情况下解决问题。
  • @David Heffernan 我使用线程来发送电子邮件,我使用 indy 组件来构建我的项目,当我发送电子邮件时,我的项目冻结了几秒钟,所以这是让我使用的主要问题线程,非常感谢。
【解决方案2】:

您的代码,修正后仅在主线程中执行 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 的回答。那里有注意事项。

【讨论】:

    【解决方案3】:

    亚当,

    如果你使用 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;
    

    【讨论】:

      【解决方案4】:

      根据@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 上编写并测试过。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-21
        • 1970-01-01
        • 2010-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-08
        相关资源
        最近更新 更多