Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在GUI更新期间保持Delphi应用程序的响应性?_Delphi_User Interface - Fatal编程技术网

如何在GUI更新期间保持Delphi应用程序的响应性?

如何在GUI更新期间保持Delphi应用程序的响应性?,delphi,user-interface,Delphi,User Interface,这个问题是关于在长时间运行的任务(大多数情况下是几秒钟)中保持GUI的响应性 我广泛使用线程和任务模式在后台线程中执行昂贵的任务。但是需要一些时间的GUI更新呢?例如,填充大字符串网格或树视图?线程在这里没有帮助,因为无论如何都需要与主线程同步 我知道Application.ProcessMessages的问题,但目前它似乎是在GUI更新方法中调用ProcessMessages的唯一解决方案 有更好的主意吗?看看。您试用过Indy的防冻成分吗?您的应用程序有什么问题吗?Application.P

这个问题是关于在长时间运行的任务(大多数情况下是几秒钟)中保持GUI的响应性

我广泛使用线程和任务模式在后台线程中执行昂贵的任务。但是需要一些时间的GUI更新呢?例如,填充大字符串网格或树视图?线程在这里没有帮助,因为无论如何都需要与主线程同步

我知道
Application.ProcessMessages
的问题,但目前它似乎是在GUI更新方法中调用
ProcessMessages
的唯一解决方案


有更好的主意吗?

看看。

您试用过Indy的防冻成分吗?

您的应用程序有什么问题吗?Application.ProcessMessages方法正是针对这种情况的。Application.ProcessMessages的问题在于如下代码:

repeat
  Application.ProcessMessages;
until SomethingHappens;
这是不好的,因为它是无用的CPU负载,应该用

repeat
  Application.HandleMessage;
until SomethingHappens;

这会将处理器时间分配给其他线程。单个Application.ProcessMessages调用(不在循环中)正常。

填充网格、列表、数据集等时,调用BeginUpdate/EndUpdate DisableControls/EnableControls。这会节省你的时间。我还有一个线程可以进行一些计算,但是GUI速度很慢,直到我调用了正在修改的数据集上的DisableControls,这些数据集由于控件位于另一个选项卡上而不可见


此外,在更新控件时,准备好所需的所有数据,这样您就可以填写列表,而无需进行会减慢速度的计算。

如果您只想处理绘制消息,而不想处理其他内容:请使用以下内容,而不是Application.ProcessMessages:

procedure ProcessPaintMessages;
var
  Msg: TMsg;
  i: Integer;
begin
  i := 0;
  repeat
    if Windows.PeekMessage(Msg, 0, 0, 0, PM_REMOVE or (QS_PAINT shl 16)) then begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end else Break;
    Inc(i);
  until i > 1000; // Breakout if we are in a paint only loop!
end;

在我看来,如果GUI更新是瓶颈(即使按照@the_Fox的建议使用BeginUpdate/EndUpdate),那么是时候重新考虑使用的GUI控件了。standart网格、treeviews和列表框并不是简单地用于处理大量项目。有许多表演第三方控制都是免费的和商业的


对于初学者,如果瓶颈在网格、树视图或列表框上下文中,请查看VirtualTreeview。

我认为“多线程”标记不适用于该问题。这不是唯一的问题。你也可以很容易地得到重入问题之类的东西。重入跟踪是应用程序逻辑的问题。你不能责怪一般的消息处理方法。当然,在GUI线程中执行耗时的操作时,某些事件的处理方式应该有所不同。我知道这一点,现在我正在使用
ProcessMessages
。我不知道它是否出了什么问题……这就是我问的原因。嗯,错误的事情是在GUI线程中执行耗时的操作。从理论上讲,总是可以避免的。实际上,并非总是如此。Application.ProcessMessages就是针对这种情况的。@Serg:重新进入的问题来自这样一个事实,即每次调用这些方法时,都会给应用程序提供一个机会,让它以一种它可能不期望的方式响应用户。因此,除非您随后添加额外的代码来禁用用户输入源,以防用户“点击风暴”,否则使用这些方法只是为了保持UI响应(在这种情况下,这是典型的,似乎是关于“及时更新”,而不是实际上“响应用户”)是自找麻烦。他指的是填充GUI组件时出现的问题,而不是由于Indy TCP/IP框架的阻塞性而冻结。您认为防冻剂在内部有什么作用?很有趣。但是循环条件从何而来?如果我每次调用该函数都要执行1000次重绘,那么这将是相当昂贵的…我在一个地方使用它,我只每隔200毫秒调用一次,所以处理1000条消息似乎并不过分。您可以将最大循环计数作为参数。请注意,此功能通常不处理任何消息或1条消息。条件只是为了避免绘制消息“失控”。@Smasher:如果是这样,您可能对大数据集使用了不合适的控件。例如,使用虚拟树控件(或类似的虚拟控件)不应该有延迟。按需加载数据(例如,当树节点展开时)也会有所帮助。此外,可能一次看到的数据太多,用户无法处理所有数据?过滤可能是一个选项。@mghi:我使用TMS字符串网格组件和默认的treeView(我知道它非常慢)。无论如何,我希望避免(如果可能的话)切换到其他组件,因为很难保持相同的外观(这里我主要关注字符串网格)。另外,还有一些过滤选项,但我不能强迫用户实际使用它们。@Smasher:嗯,使用
OnCollapsed
OnExpanding
将有助于加快标准树状图的速度。标准树状图很糟糕。更改为VirtualTreeView(见下文)我可以在商业应用程序中使用虚拟树视图吗?将列表视图或树视图更改为[VirtualTreeView][1]。在Delphi 2009/2010中,调试消息“列表视图”实际上是一个虚拟的树状视图,因为其他控件的项目不断插入,更新速度太慢,无法满足用户的期望。你似乎也有类似的问题。您想要的是更快的GUI控件。[1]: