下面只是两个线程中的2个按钮之间的简单比赛,
这将冻结表单上的其他组件。
procedure moveButton1();
var
I: Integer;
begin
for I := 0 to 6000 do
Form1.Button1.Left := Form1.Button1.Left - 1;
Form1.Caption := 'Button1 won!';
EndThread(0);
end;
procedure moveButton2();
var
I: Integer;
begin
for I := 0 to 6000 do
Form1.Button2.Left := Form1.Button2.Left - 1;
Form1.Caption := 'Button2 won!';
EndThread(0);
end;
procedure TForm1.Button3Click(Sender: TObject);
var
thread1, thread2,tick : Integer;
id1, id2 : LongWord;
begin
thread1 := BeginThread(nil,
0,
Addr(moveButton1),
nil,
0,
id1);
thread2 := BeginThread(nil,
0,
Addr(moveButton2),
nil,
0,
id2);
CloseHandle(thread1);
CloseHandle(thread2);
end;
答案 0 :(得分:10)
VCL(以及部分RTL)不是线程安全的,因此您无法从线程中移动组件。您有几种选择:
TTimer
组件。您不需要线程,并且计时器的事件处理程序将在主线程的上下文中执行。计时器的设计完全符合这类。TThread
提供了一种静态方法Synchronize
。SendMessage
或PostMessage
将消息从帖子发送到表单,并在表单中处理此消息。在使用线程时,您可能还会考虑使用TThread
包装类而不是显式使用BeginThread
和EndThread
。
答案 1 :(得分:0)
使用Synchronize()将是同步移动按钮的过程的向下和脏的方法。 Synchronize()强制该方法在主VCL线程中运行。它们会相互阻挡,因此一次只能移动一个按钮。这样可以避免在VCL中遇到非线程安全的代码。
我无法重新创建表单冻结的问题,所以我不确定这是你的问题。你可能希望到别处去看看。