Системная ошибка Delphi, код 5, доступ запрещен

Я создал тему, и она хорошо работает, когда 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.

1 ответ

Если вы посмотрите на исходный код TVCLReport, его Execute() метод отображает пользовательский интерфейс на основе VCL, когда 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 не являются поточно-ориентированными и не могут использоваться вне контекста основного потока пользовательского интерфейса. Как вы видете, TVCLReport.Execute() не предоставляет никакой возможности синхронизироваться с основным потоком пользовательского интерфейса, поэтому 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 в главном потоке пользовательского интерфейса и отображать сообщение пользователю, пока он занят созданием отчета.

Вам просто нужно попробовать и посмотреть, что получится.

Другие вопросы по тегам