在长时间的任务中保持应用响应 [英] Keep app responsive during long task

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

问题描述

我们应用程序中的某种形式显示模型的图形视图.用户可以在大量其他内容中启动模型转换,这可能需要相当长的时间.这种转换有时在没有任何用户交互的情况下进行,有时则需要频繁的用户输入.除非需要用户输入,否则应禁用 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:与回调相同的问题.此外,您还会遇到 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天全站免登陆