在长任务期间保持应用程序响应 [英] Keep app responsive during long task

查看:112
本文介绍了在长任务期间保持应用程序响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们应用程序中的某种形式显示模型的图形视图。用户可以在其他东西的负载中启动模型的转换,这可能需要相当长的时间。这种变换有时在没有任何用户交互的情况下进行,在其他时候,频繁的用户输入是必要的。除非需要用户输入,否则应该禁用UI(只显示进度对话框)。

A certain form in our application displays a graphical view of a model. The user can, amongst loads of other stuff, initiate a transformation of the model that can take quite some time. This transformation sometimes proceeds without any user interaction, at other times frequent user input is necessary. While it lasts the UI should be disabled (just showing a progress dialog) unless user input is needed.

可能的方法:


  1. 忽略问题,只需将转换代码放在过程中并调用即可。糟糕,因为应用程序似乎挂起的情况下,转换需要一些时间,但不需要用户输入。

  2. 使用回调函数调用代码:这是突兀的 - 你必须放一个很多在转换代码中的调用 - 以及不可预测的 - 你永远不能确定你找到了正确的点。

  3. 用Application应用程序代码。 ProcessMessages:与回调相同的问题。

  4. 使用一个线程:这使我们免于使用2.和3的干扰性和不可预测性部分。然而,这是很多工作,因为用户输入所需的编组 - 调用Synchronize,在定制的记录中添加任何所需的参数等。这也是调试和容易出错的噩梦。

  1. Ignore the issue, just put the transformation code in a procedure and call that. Bad because the app seems hung in cases where the transformation needs some time but requires no user input.
  2. Sprinkle the code with callbacks: This is obtrusive - you’d have to put a lot of these calls in the transformation code - as well as unpredictable - you could never be sure that you’d found the right spots.
  3. Sprinkle the code with Application.ProcessMessages: Same problems as with callbacks. Additionally you get all the issues with ProcessMessages.
  4. Use a thread: This relieves us from the "obtrusive and unpredictable" part of 2. and 3. However it is a lot of work because of the "marshalling" that is needed for the user input - call Synchronize, put any needed parameters in tailor-made records etc. It’s also a nightmare to debug and prone to errors.

//编辑:我们当前的解决方案是一个线程。然而,这是一个痛苦在a **因为用户输入。并且在很多例程中可能有很多输入代码。这给我一种感觉,一个线程正确的解决方案。

// Our current solution is a thread. However it's a pain in the a** because of the user input. And there can be a lot of input code in a lot of routines. This gives me a feeling that a thread is not the right solution.

我要尴尬自己,我创建的GUI和工作代码的混合:

I'm going to embarass myself and post an outline of the unholy mix of GUI and work code that I've produced:

type
  // Helper type to get the parameters into the Synchronize'd routine:
  PGetSomeUserInputInfo = ^TGetSomeUserInputInfo;
  TGetSomeUserInputInfo = record
    FMyModelForm: TMyModelForm;
    FModel: TMyModel;
    // lots of in- and output parameters
    FResult: Boolean;
  end;

{ TMyThread }

function TMyThread.GetSomeUserInput(AMyModelForm: TMyModelForm;
  AModel: TMyModel; (* the same parameters as in TGetSomeUserInputInfo *)): Boolean;
var
  GSUII: TGetSomeUserInputInfo;
begin
  GSUII.FMyModelForm := AMyModelForm;
  GSUII.FModel := AModel;
  // Set the input parameters in GSUII

  FpCallbackParams := @GSUII; // FpCallbackParams is a Pointer field in TMyThread
  Synchronize(DelegateGetSomeUserInput);
  // Read the output parameters from GSUII
  Result := GSUII.FResult;
end;

procedure TMyThread.DelegateGetSomeUserInput;
begin
  with PGetSomeUserInputInfo(FpCallbackParams)^ do
    FResult := FMyModelForm.DoGetSomeUserInput(FModel, (* the params go here *));
end;

{ TMyModelForm }

function TMyModelForm.DoGetSomeUserInput(Sender: TMyModel; (* and here *)): Boolean;
begin
  // Show the dialog
end;

function TMyModelForm.GetSomeUserInput(Sender: TMyModel; (* the params again *)): Boolean;
begin
  // The input can be necessary in different situations - some within a thread, some not.
  if Assigned(FMyThread) then
    Result := FMyThread.GetSomeUserInput(Self, Sender, (* the params *))
  else
    Result := DoGetSomeUserInput(Sender, (* the params *));
end;

您有任何意见吗?

推荐答案

我认为只要你的长期运行的转换需要用户交互,你不会真正满意任何答案。所以,让我们回来一会儿:为什么你需要中断转换与请求更多的信息?这些真正的问题,你不能预料到开始转型之前?当然,用户对于中断不是太高兴,对吧?他们不能只是设置转变,然后去得到一杯咖啡;他们需要坐下来观看进度条,以防万一有问题。唉。

I think as long as your long-running transformations require user interaction, you're not going to be truly happy with any answer you get. So let's back up for a moment: Why do you need to interrupt the transformation with requests for more information? Are these really questions you couldn't have anticipated before starting the transformation? Surely the users aren't too happy about the interruptions, either, right? They can't just set the transformation going and then go get a cup of coffee; they need to sit and watch the progress bar in case there's an issue. Ugh.

也许转换遇到的问题是可以保存直到结束的事情。变换需要立即知道答案,还是可以完成一切,然后只是做一些修复之后?

Maybe the issues the transformation encounters are things that could be "saved up" until the end. Does the transformation need to know the answers immediately, or could it finish everything else, and then just do some "fix-ups" afterward?

这篇关于在长任务期间保持应用程序响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆