我们的应用程序中的某个表单显示模型的图形视图.用户可以在其他东西的负载中启动模型的转换,这可能需要相当长的时间.有时在没有任何用户交互的情况下进行该转换,在其他时候需要频繁的用户输入.虽然它会持续,但应禁用UI(仅显示进度对话框),除非需要用户输入.
可能的方法:
忽略这个问题,只需将转换代码放在一个过程中并调用它.不好,因为在转换需要一些时间但不需要用户输入的情况下应用程序似乎挂起.
使用回调来填充代码:这是突兀的 - 你必须在转换代码中加入大量这些调用 - 以及不可预测的 - 你永远无法确定你找到了正确的位置.
使用Application.ProcessMessages填充代码:与回调相同的问题.此外,您还可以获得ProcessMessages的所有问题.
使用线程:这使我们免于2.和3的"突兀和不可预测"部分.然而,由于用户输入所需的"编组",它需要做很多工作 - 调用Synchronize,将所需的任何参数放入定制的记录等.这也是调试和容易出错的噩梦.
//编辑:我们当前的解决方案是一个线程.然而,由于用户输入,这是一个痛苦的**.在很多例程中可能会有很多输入代码.这让我感觉线程不是正确的解决方案.
我将自己进行尴尬并发布我生成的GUI和工作代码的混合组合的大纲:
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;
你有什么意见吗?
我认为只要您长期运行的转换需要用户互动,您就不会对任何答案感到满意.所以让我们回顾一下:为什么你需要通过请求获取更多信息来中断转换?在开始转型之前,这些问题真的是你无法预料到的吗?当然,用户对中断也不太满意,对吧?他们不仅可以设定转型,还可以获得一杯咖啡; 如果出现问题,他们需要坐下来观看进度条.啊.
也许转型遇到的问题是可以"储存"到最后的事情.转换是否需要立即知道答案,还是可以完成其他所有事情,然后再做一些"修复"?