【问题标题】:Delphi Access Violation when moving button on form移动表单上的按钮时Delphi访问冲突
【发布时间】:2015-06-08 09:39:47
【问题描述】:

我正在尝试使用 while 循环检查按钮左侧属性来移动表单上的 2 个按钮,但我遇到了访问冲突。我正在使用 CreateThread() 执行该过程

The code:

procedure AnimButton1();
var ImageCount: integer;
var b1, b2: integer;
begin

  try

       while (b2 <> 187) do
       begin
           b2 := frmNotification.btnBuzina2.Left;
           frmNotification.btnBuzina2.Left := b2 - 1;

       end;

       while (b1 <> 256) do
       begin
           b1 := frmNotification.btnBuzina.Left;
           frmNotification.btnBuzina.Left := b1 - 1;

       end;

  except;
  end;

end;

但是,当我使用 Sleep() 至少 5 毫秒时,我没有访问冲突,如下所示:

procedure AnimButton1();
var ImageCount: integer;
var b1, b2: integer;
begin

  try

       while (b2 <> 187) do
       begin
           b2 := frmNotification.btnBuzina2.Left;
           frmNotification.btnBuzina2.Left := b2 - 1;
           Sleep(5);
       end;

       while (b1 <> 256) do
       begin
           b1 := frmNotification.btnBuzina.Left;
           frmNotification.btnBuzina.Left := b1 - 1;
           Sleep(5);
       end;

  except;
  end;

end;

有人可以帮我找出为什么没有睡眠我会获得访问冲突,而我却没有?

提前谢谢!

【问题讨论】:

  • 在使用“while ...”测试它们的值之前,您省略了初始化 b1 和 b2。它们在进入 AnimButton1 时会有随机值。
  • 请告诉我们发生异常的确切消息,并在上面的代码中标记该行以显示代码中断的位置。
  • 例外是prntscr.com/7emu4e 发生在'end;'之前的while内

标签: delphi button access-violation


【解决方案1】:

我正在使用CreateThread() 执行该过程。

那是你的问题。 VCL 代码只能从主 UI 线程调用。使用TThread.Synchronize在主线程调用VCL代码。

也就是说,计时器可能比线程更适合解决您的问题。

【讨论】:

  • 可能他的主线程正忙于一些长操作,所以他试图以错误的方式修复它。他没有将长操作卸载到辅助线程中,而是尝试在那里偏移主用户 UI。
  • 也就是说,我相信他可以使用Windows GDI层从辅助线程中移动按钮,但如果他的VCLMainThread被锁定在一些长时间的计算中,它会无法及时执行WM_PAINT
  • 使用计时器,主线程冻结,只有在整个进程结束时才解冻。我想我真的需要一个跑出主线程的线程。
  • 那是因为您在主 UI 线程中完成所有工作。您需要将长时间运行的任务放在工作线程中,并在 UI 线程中处理 UI。一个计时器就可以了。
  • 定时器在执行动作时仍然锁定界面。即使我放了一个 sleep()。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多