如果看一下供TVCLReport
的源代碼,其Execute()
方法顯示當Preview=True
基於VCL-UI:
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
對象放置在與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線程中可能更容易,並且在忙於生成報告時向用戶顯示消息。
你只需要嘗試一下,看看會發生什麼。
非常感謝你的努力和想法。我很感激。我會試一試,讓它知道它是否有效。 – ErenRavenHeart
我無法弄清楚......「dm.rmvFarm.DisplayPreview」,「dm.rmvFarm.OnPreview」未申報。 – ErenRavenHeart
@ErenRavenHeart您可能有另一個ReportManager版本,而不是Remy。或者你沒有在你的Uses子句中包含適當的源文件。使用文檔。 –