我有这样的代码:
procedure TSeries.Read;
var
ReadProc: TParallelFunction2;
Counter: integer;
begin
try
ProgressForm.Show;
Counter := 0;
ReadProc :=
procedure (i1, i2, tdi: integer)
var
i: integer;
begin
for i := i1 to i2 do
if not FDASlice[i].PctPresent then
begin
TInterlocked.Increment(Counter);
ReadSlice(i, True);
end;
end;
Parallel.ForI(0, High, ReadProc, pfDivide);
finally
ProgressForm.HideForm;
end;
end;
它使用STParallel库在多线程模式下处理ReadProc过程。一切正常,但我需要向用户显示进度。 我尝试将'Application.ProcessMessage'+'ProgressForm.SpTBXProgressBar1.Position:= Counter'添加到ReadProc中,或者'TThread.Synchronize'没有成功。应用程序挂起,进度未显示。
我如何才能显示进度?是否有可能在该代码中,或者需要将所有非主线程移动到其他位置?谢谢。
答案 0 :(得分:5)
处理此问题的最简单,最好的方法是让主线程更新计时器的进度。
您需要为进度计数器提供计时器事件访问权限。这意味着将Counter
变量从局部变量转换为UI可以访问的类的变量。您不需要同步对计数器的访问,因为UI没有修改它,并且您已经使用原子增量函数来修改计数器。
因此,您需要的步骤是:
Counter
变量移动为类的成员,UI可以访问该类。那为什么这种方法比你的更好?好吧,进度UI更新不应该由工作线程驱动。这样做会冒着刷新UI的风险。这可能严重阻碍性能和可扩展性。
让工作人员更新进度状态,但让UI继续负责驱动更新。 UI知道没有太频繁刷新的点,只有它能够确定刷新率。