【问题标题】:Display progress from time consuming process显示耗时过程的进度
【发布时间】:2009-10-19 20:58:01
【问题描述】:

对不起我的英语不好... 使用 Delphi 7,我想创建一个对话框窗口,以显示当我必须运行缓慢的进程时,我的应用程序中正在发生某些事情。 我的想法是做一些我可以使用的事情:

with TMyDialog.Create do
begin
  //call the time consuming method here
  Free;
end;

当我创建对话框时,将显示一个带有动画或其他内容的窗口,并在耗时方法结束后消失(在免费方法上) - 如果我可以手动更新该对话框的进度,那就太好了,在流程向我提供此类信息的情况:

with TMyDialog.Create do
begin
  while time_consuming_method do
  begin
    UpdateStatusOnMyDyalog();
  end;
  Free;
end;

但通常它只是一个动画来显示正在发生的事情。

有没有人做过类似的事情,知道一个组件,或者对用最干净和最简单的方式做这件事的最佳方法有什么建议?

【问题讨论】:

    标签: delphi user-interface dialog


    【解决方案1】:

    执行此操作的糟糕但简单的方法是调用Application.ProcessMessagesUpdateWindow(Handle)(以更新表单)并在time_consuming_method 期间增加一个进度条。更好的方法是将您的time_consuming_method 包装到一个带有 OnProgress 事件的类中。最后,正如其他人建议的那样,您可以为 time_consuming_method 使用单独的线程 - 这是最强大的技术,但学习曲线最差。

    【讨论】:

    • 是的,感谢您的回复...我试图避免使用 TThread 方式 - 我在想对于如此简单的事情必须有另一种方式,我猜我错了 - 我不知道不知道为什么,但每次我查看一些 delphi 的多线程代码时,我都认为“这里有问题”:/
    • 问题是要真正顺利完成几乎是不可能的。使其顺利进行的唯一方法是,如果您可以保证 time_sumption_method 中的片段非常短。
    【解决方案2】:

    您需要在单独的线程中运行耗时的进程,并让该线程使用同步向您的主 UI 线程报告其进度。

    Here is an example 向您展示如何启动一个新线程并让该线程执行同步进度报告。

    --杰罗恩

    【讨论】:

      【解决方案3】:

      以这种方式报告进度是很常见的(例如,使用进度条)。

      您的“耗时过程”需要接收一个回调函数,该回调函数将在每次需要报告一些进展时被调用,或者,如果您愿意将它与您的用户界面设计更紧密地绑定,则需要一个对组件的引用某种它会知道如何更新的东西。这可以是一个进度条,它可以单步执行,一个列表框或备注字段将接收一个新的状态更新行,一个标签控件,其标题将得到更新,等等。

      【讨论】:

        【解决方案4】:

        在长时间操作期间显示进度取决于几个因素(限制):

        • 已定义/未定义的进度(你知道, 可以计算一下,做了多少步 操作)
        • 可中断性/分段(您 将能够或不得不打断 刷新进度的操作 给用户)
        • 该操作是可线程的(您可以 把操作放到一个线程中)

        对于已定义的进度,通常显示分段进度条,而对于未定义的动画或进度条,通常会显示“Marquee”样式。

        主要考虑的是操作是否是分段/可中断的。因为如果不是,并且您不处理它,您的应用程序将冻结,直到操作完成。 搜索文件是分段操作的一个例子。每个找到的文件都是一个段,它使您能够向用户显示进度并刷新显示。

        例子:

        TFrmUndefinedProgress = class(TForm)
        private
           FCallbackProc           : TNotifyEvent;
        protected
           procedure WndProc(var Message:TMessage); override;
        public
           constructor Create(aCallbackProc: TNotifyEvent);
          procedure UpdateProgress(const aStr : string; aPercent : integer); 
        ...
        constructor TFrmUndefinedProgress.Create(aCallbackProc: TNotifyEvent);
        begin
           inherited Create(nil);
           FCallbackProc     := aCallbackProc;
        end;
        ...
        procedure TFrmUndefinedProgress.FormShow(Sender: TObject);
        begin
           Update;
           PostMessage(Handle, WM_START_UNDEFPROG, 0, 0); 
        end;
        

        在表单的 OnShow 上向窗口过程发送消息,以确保它首先被呈现。

        procedure TFrmUndefinedProgress.WndProc(var Message: TMessage);
        begin
           if (Message.Msg = WM_START_UNDEFPROG) then begin
              if Assigned(FCallbackProc) then
                 FCallbackProc(Self); --> Call your callback procedure
           PostMessage(Handle, WM_CLOSE, 0, 0); --> close when finished
           end
           else
           inherited;
        end;
        

        如果您在表单单元中进行常规程序...

        procedure ShowUndefinedProgress(aCallbackProc : TNotifyEvent);
        var
           FrmUndefinedProgress : TFrmUndefinedProgress;
        begin
           FrmUndefinedProgress := nil;
           try
              FrmUndefinedProgress         := TFrmUndefinedProgress.Create(aCallbackProc);
              FrmUndefinedProgress.ShowModal;
           finally
              FreeAndNil(FrmUndefinedProgress);
           end;
        end;
        

        然后你可以这样调用进度表:

        ShowUndefinedProgress(HandleSomeOperation);
        

        你在哪里传递你的 aCallbackProc。 你把你的操作放在里面:

        procedure TForm1.HandleSomeOperation(Sender: TForm);
        var
           aProgress : TFrmUndefinedProgress;
        begin
           --> Do something
           aProgress := TFrmUndefinedProgress(Sender);
           aProgress .UpdateProgress(SomeMessage, Percent);
        

        更新每个找到的文件的显示...

        如果你有一个操作需要很长时间,但是你没有办法中断它,那么你应该把它放在一个线程中。

        • 创建 TThread 对象的后代。
        • 覆盖它的 Execute 方法
        • 在执行里面做你的事 并使用它:
        • 创建表单
        • 在它的 OnShow 上开始一些动画
        • 然后运行你的线程
        • 线程结束时关闭。

        【讨论】:

          猜你喜欢
          • 2021-08-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-11
          • 2013-12-28
          • 1970-01-01
          • 1970-01-01
          • 2013-11-30
          • 1970-01-01
          相关资源
          最近更新 更多