[英]Delphi and threads: “System Error. Code: 1400. Invalid window handle”
[英]Delphi system error code 5 access denied
我創建了一個線程,當Preview=false
時工作良好,但是當我設置Preview=true
我總是收到錯誤消息(系統錯誤代碼5訪問被拒絕)。
我想對報告進行處理,因為生成報告需要10秒鍾以上。
有人可以解釋發生了什么嗎?
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.Execute;
ReportThread1.free;
end;
end.
如果查看TVCLReport
的源代碼, TVCLReport
在Preview=True
時,其Execute()
方法將顯示基於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()
一起顯示的自定義TForm
對象( TFRpPreview
)上。 基於VCL的用戶界面不是線程安全的,因此不能在主用戶界面線程的上下文之外使用。 如您所見, 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線程中,並在忙於生成報告時向用戶顯示一條消息可能會更容易。
您只需要嘗試一下,看看會發生什么。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.