首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在调用Beginthread API时避免GUI冻结?

如何在调用Beginthread API时避免GUI冻结?
EN

Stack Overflow用户
提问于 2010-03-24 22:02:19
回答 2查看 2.1K关注 0票数 0

下面是两个线程中两个按钮之间的简单竞争,

这将冻结表单上的其他组件。

代码语言:javascript
复制
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;
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-03-24 22:12:52

VCL (和RTL的一部分)不是线程安全的,因此您不能从线程中移动组件。您有几个选项:

  • 使用TTimer组件。您不需要线程,定时器的事件处理程序将在主线程的上下文中执行。计时器是专门为线程中所有与VCL相关的东西设计的,比如that.
  • Synchronize。TThread提供了一个执行此操作的静态方法Synchronize
  • 使用SendMessagePostMessage将消息从线程发送到窗体,并在窗体中处理此消息。

在处理线程时,您还可以考虑使用TThread包装类,而不是显式地使用BeginThreadEndThread

票数 10
EN

Stack Overflow用户

发布于 2010-03-25 03:09:46

使用Synchronize()将是同步移动按钮的过程的一种非常糟糕的方法。Synchronize()强制方法在主VCL线程中运行。它们会互相阻挡,所以一次只能移动一个按钮。这将避免在VCL中遇到非线程安全代码。

我不能重现表单冻结的问题,所以我不确定这是你的问题。你可能想看看别的地方。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2508216

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档