立即在Delphi中运行下一行



我这里有一些代码:

procedure TForm1.Button1Click(Sender: TObject);
begin
  //Some Codes(1)
  Sample;
  //Some Codes(2)
end;
Function Sample();
begin
  sleep(5000);
end;

在这段代码中,在//Somecodes(1)应用程序转到Sample功能并等待5秒后,它运行//Somecodes(2),对吗?这意味着对于解冻Button1,我们必须等待5秒以上。

现在,我想做一些事情,当应用程序运行//Some Codes(1)Sample时,立即转到下一行(//Somecodes(2)),这样我就不需要等待5秒钟来单击1解冻。

我该怎么做?

正如Andreas所说,您可以为此使用线程。您可以将它们与这样的匿名过程一起使用:(注意:TThread.CreateAnonymousThread在Delphi 2010中似乎还不存在。我在下面解决这个问题。)

procedure TForm1.Button1Click(Sender: TObject);
begin
  TThread.CreateAnonymousThread(
    procedure
    begin
      // Chunk of code 1
      Sleep(5000);
      MessageBox(0, 'x', 'x', MB_OK);
    end).Start;
  TThread.CreateAnonymousThread(
    procedure
    begin
      // Chunk of code 2
      Sleep(5000);
      MessageBox(0, 'y', 'y', MB_OK);
    end).Start;
end;

您也可以实现自己的线程类,但使用CreateAnonymousThread可以只传递在线程中执行的过程。您可以调用Start(或Run)来立即运行线程,使用CreateAnonymousThread创建的线程在完成后会释放自己。

因此,两个代码块将同时运行。这意味着5秒钟后,你会得到两个紧接着的弹出窗口(你可以把最上面的拖到一边看另一个)。此外,当睡眠在后台运行时,单击按钮后会直接做出响应。

不过请注意,大多数VCL都不是线程安全的,所以您应该小心不要修改这些线程中的(可视化)组件。

关于线程安全

就像评论中提到的J一样,不仅仅是VCL是线程安全的。许多代码都不是,而且您自己的代码也需要意识到这一点。例如,如果我稍微修改上面的代码,我可以让两个线程都计数为十亿,并增加一个共享整数。当线程完成时,您可能会期望整数达到20亿,但在我的测试中,它刚刚超过10亿。这是因为两个线程同时更新同一个整数,覆盖了另一个线程的尝试。

procedure TForm6.FormCreate(Sender: TObject);
var
  n: Integer;
begin
  n := 0;
  TThread.CreateAnonymousThread(
    procedure
    var i: Integer;
    begin
      for i := 0 to 1000000000 do
        Inc(n);
      MessageBox(0, 'x', 'x', MB_OK);
    end).Start;
  TThread.CreateAnonymousThread(
    procedure
    var i: Integer;
    begin
      for i := 0 to 1000000000 do
        Inc(n);
      MessageBox(0, 'y', 'y', MB_OK);
    end).Start;
  Sleep(10000); // Make sure this is long enough. The number should appear later than 'x' and 'y'.
  ShowMessage(IntToStr(n));
end;

要解决此问题,您可以同步更新(在主线程中执行),或者使用关键部分锁定更新。在实际只是整数更新的情况下,也可以使用InterlockedIncrement函数。我不会进一步解释这些,因为有很多适当的文件,这超出了这个答案的范围。

不过,请注意,这些方法中的每一个都会通过一个接一个而不是同时执行代码来减慢应用程序的速度。您实际上是在让线程相互等待。尽管如此,如果您可以对线程进行微调,使其只需要同步小部分,那么线程仍然很有用。

TThread.CreateAnonymousThread在Delphi 2010中

TThread.CreateAnonymousThread只是创建一个TAnonymousThread实例,这是一个执行给定过程的特定线程类。

由于TThread.CreateAnonymousThread在Delphi2010中不存在,您可以这样调用它:

  TAnonymousThread.Create(
    procedure
    var i: Integer;
    begin
      for i := 0 to 1000000000 do
        Inc(n);
      MessageBox(0, 'x', 'x', MB_OK);
    end).Start;

我不知道TAnonymousThread本身是否在Delphi2010中存在,但如果不存在,你可以在下面找到它的代码。我希望Embarcadero不介意我分享它,但它实际上只是四行简单的代码。

这个类你可以很容易地自己创建,但它的声明如下。构造函数采用单个参数,该参数是要执行的过程。它还设置了一个属性,使线程在完成时释放自己。execute方法只是执行给定的过程。

type
  TAnonymousThread = class(TThread)
  private
    FProc: TProc;
  protected
    procedure Execute; override;
  public
    constructor Create(const AProc: TProc);
  end;
constructor TAnonymousThread.Create(const AProc: TProc);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  FProc := AProc;
end;
procedure TAnonymousThread.Execute;
begin
  FProc();
end;

最新更新