我这里有一些代码:
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。
我该怎么做?
答案 0 :(得分:9)
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;