TThread.Execute 未按预期调用

发布于 2024-09-17 21:03:19 字数 847 浏览 4 评论 0原文

我试图在应用程序的长时间操作期间显示指示覆盖(旋转的圆点)的活动。为此,我创建了一个带有 TImage 和 Imagelist 的无边框透明表单,我试图在主线程繁忙时在线程中更新它。

我遇到的问题是,冗长的操作似乎没有被我的线程“中断”。 thread.Execute 函数在冗长的操作开始之前循环几次,然后在操作完成时再次循环。

看起来好像线程由于某种原因而处于饥饿状态。我试图提高它的优先级,但看不到任何效果。

有没有人有类似的经验可以分享,或者甚至是解决方案?


线程函数源码

procedure TIndicatorThread.Execute;
begin
  inherited;
  while(not Terminated) do
    begin
      fDlg.fCurindex := (fDlg.fCurindex+1) mod 12;
      Synchronize(UpdateImage);
      Application.ProcessMessages;
      sleep(80);
    end;
    Synchronize(fDlg.close);
    Synchronize(fDlg.Free);
end;

主线程

begin
[...]
myThread := TIndicatorThread.Create;
mythread.Resume;

Init_SomeUIRelatedstuff;
Application.ProcessMessages;

DoLengthyOperation; 

mythread.Terminate;

I am trying to display an activity indicating overlay (a spinning circle of dots) during a lengthy operation in my application. For this, i created a borderless transparent form with a TImage and an Imagelist, which i sought to update in a thread during the time the main thread is busy.

The problem i encountered is that the lengthy operation does not seem to get 'interupted' by my thread. The thread.Execute function loops a few times before the lengthy operation starts, and then again when the operation is finished.

It seems as if the thread is starved for some reason. I tried to raise it's priority, but could not see any effect.

Does anyone have similar experiences to share, or maybe even a solution?


Source code of thread function

procedure TIndicatorThread.Execute;
begin
  inherited;
  while(not Terminated) do
    begin
      fDlg.fCurindex := (fDlg.fCurindex+1) mod 12;
      Synchronize(UpdateImage);
      Application.ProcessMessages;
      sleep(80);
    end;
    Synchronize(fDlg.close);
    Synchronize(fDlg.Free);
end;

main thread

begin
[...]
myThread := TIndicatorThread.Create;
mythread.Resume;

Init_SomeUIRelatedstuff;
Application.ProcessMessages;

DoLengthyOperation; 

mythread.Terminate;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

木落 2024-09-24 21:03:19

您正在 Synchronize() 内部完成大部分线程工作,它将工作委托回主线程。如果主线程的冗长操作没有处理消息队列中的新消息,则 Synchronize() 必须等待。这就是为什么你的线程在长时间操作运行时不执行任何操作。

您的代码是如何有效使用线程的一个糟糕示例。相反,您应该做的是在线程中执行冗长的操作本身,并让主线程在线程运行时处理 UI 更新,例如:

procedure TWorkThread.Execute; 
begin 
  DoLengthyOperation;  
end; 

begin 
  ...
  Init_SomeUIRelatedstuff; 
  Application.ProcessMessages; 

  myThread := TWorkThread.Create(False);
  while WaitForSingleObject(myThread.Handle, 80) = WAIT_TIMEOUT do
  begin 
    fDlg.fCurindex := (fDlg.fCurindex+1) mod 12; 
    UpdateImage; 
    Application.ProcessMessages; 
  end; 
  mythread.Free;

  fDlg.Close; 
  fDlg.Free;

  ...
end;

Your are doing the bulk of your thread work inside of Synchronize(), which delegates the work back to the main thread. If the main thread's lengthy operation is not processing new messages from the message queue, then Synchronize() has to wait. That is why your thread does not do anything while the lengthy operation is running.

Your code is a poor example of how to use a thread effectively. What you should have done instead is perform the lengthy operation itself in the thread, and let the main thread handle the UI updates while the thread is running, eg:

procedure TWorkThread.Execute; 
begin 
  DoLengthyOperation;  
end; 

begin 
  ...
  Init_SomeUIRelatedstuff; 
  Application.ProcessMessages; 

  myThread := TWorkThread.Create(False);
  while WaitForSingleObject(myThread.Handle, 80) = WAIT_TIMEOUT do
  begin 
    fDlg.fCurindex := (fDlg.fCurindex+1) mod 12; 
    UpdateImage; 
    Application.ProcessMessages; 
  end; 
  mythread.Free;

  fDlg.Close; 
  fDlg.Free;

  ...
end;
挽清梦 2024-09-24 21:03:19

I used GIF image component that can show animated GIFs (http://www.tolderlund.eu/delphi/),
and I put a lengthy operation inside a timer (which
executes in separate thread).

Simple but effective.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文