如果您查看 的源代码TVCLReport
,它的Execute()
方法会在以下情况下显示基于 VCL 的 UI Preview=True
:
type
TVCLReport=class(TCBaseReport)
private
prcontrol:TRpPreviewControl;
...
end;
function TVCLReport.Execute:boolean;
var
...
begin
inherited Execute;
...
try
if Preview then
begin
prcontrol:=TRpPreviewControl.Create(nil);
try
prcontrol.Report:=Report;
Result:=ShowPreview(prcontrol,Title);
finally
prcontrol.free;
end;
end
else
begin
...
end;
TRpPreviewControl
源自TScrollBox
。 ShowPreview()
是一个辅助函数,它将TRpPreviewControl
对象放置到一个自定义TForm
对象 ( TFRpPreview
) 上,该对象与ShowModal()
. 基于 VCL 的 UI 不是线程安全的,不能在主 UI 线程的上下文之外使用。如您所见,TVCLReport.Execute()
它没有为您提供与主 UI 线程同步的任何机会,因此Preview=True
在工作线程中使用是不安全的。
如果您想调用TVCLReport.Execute()
工作线程,但以线程安全的方式显示其预览,一种可能的解决方案是更改源代码,TVCLReport
以允许您使用调用它的方式公开预览功能TThread.Synchronize()
,例如:
type
TVCLReportPreviewEvent = procedure(Sender: TObject; var VResult: Boolean) of object;
TVCLReport=class(TCBaseReport)
private
prcontrol:TRpPreviewControl;
...
public
OnPreview: TVCLReportPreviewEvent;
function DisplayPreview: Boolean;
end;
function TVCLReport.Execute:boolean;
var
...
begin
inherited Execute;
...
try
if Preview then
begin
if Assigned(OnPreview) then
OnPreview(Self, Result)
else
Result := DisplayPreview;
end
else
begin
...
end;
function TVCLReport.DisplayPreview: Boolean;
begin
prcontrol:=TRpPreviewControl.Create(nil);
try
prcontrol.Report:=Report;
Result := ShowPreview(prcontrol, Title);
finally
prcontrol.free;
end;
end;
procedure TReportThread1.Execute;
begin
if ReportBUFFER = 1 then begin
dm.rmvFarm.Filename := reportpath + 'aoc.rep';
dm.rmvFarm.Report.Params.Items[0].Value := Thread_StartOfTheDayR1;
dm.rmvFarm.Report.Params.Items[1].Value := Thread_EndOfTheDayR1;
dm.rmvFarm.Report.Params.Items[2].Value := currentusr;
dm.rmvFarm.Preview := true;
dm.rmvFarm.OnPreview := DisplayPreviewInMainThread;
dm.rmvFarm.Execute;
ReportThread1.free;
end;
end;
procedure TReportThread1.DisplayPreviewInMainThread(Sender: TObject; var VResult: Boolean);
begin
TThread.Synchronize(nil,
procedure
begin
VResult := dm.rmvFarm.DisplayPreview;
end
);
end;
虽然,如果您的报告确实需要很长时间才能生成,那么预览也可能需要很长时间才能生成。如果是这样,此解决方案不会为您带来任何有用的东西。简单地将 留TVCLReport
在主 UI 线程中,并在用户忙于生成报告时向用户显示一条消息可能会更容易。
您只需要尝试一下,看看会发生什么。