在Delphi中立即运行下一行

时间:2013-07-16 19:02:32

标签: delphi delphi-2010

我这里有一些代码:

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 Unfreez。

我该怎么做?

1 个答案:

答案 0 :(得分:9)

像安德烈亚斯说的那样,你可以使用线程。您可以使用这样的匿名过程:(注意:在Delphi 2010中,TThread.CreateAnonymousThread似乎不存在。我在下面解决了这个问题。)

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函数。我不会进一步解释这些,因为有大量适当的文档,这超出了这个答案的范围。

但请注意,这些方法中的每一种都会通过彼此之后执行代码而不是同时执行来减慢应用程序的速度。你有效地使线程彼此等待。尽管如此,如果您可以对线程进行微调,那么线程仍然很有用,因此只需要对小块进行同步。

在Delphi 2010中使用TThread.CreateAnonymousThread

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

由于在Delphi 2010中不存在TThread.CreateAnonymousThread,您可以这样称呼它:

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

我不知道Delphi 2010中是否存在TAnonymousThread本身,但如果没有,您可以在下面找到它的代码。我希望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;