【问题标题】:Delphi system error code 5 access deniedDelphi系统错误代码5访问被拒绝
【发布时间】:2015-10-20 03:15:10
【问题描述】:

我创建了一个线程,它在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.

【问题讨论】:

    标签: multithreading delphi reportmanager


    【解决方案1】:

    如果您查看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 派生自 TScrollBoxShowPreview() 是一个辅助函数,它将TRpPreviewControl 对象放置到与ShowModal() 一起显示的自定义TForm 对象(TFRpPreview) 上。基于 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 线程中并在用户忙于生成报告时向用户显示一条消息可能会更容易。

    您只需尝试一下,看看会发生什么。

    【讨论】:

    • 非常感谢您的努力和想法。我很感激。我会试一试,让你知道它是否有效。
    • 我想不通..."dm.rmvFarm.DisplayPreview", "dm.rmvFarm.OnPreview" 未声明..
    • @ErenRavenHeart 您可能拥有比 Remy 拥有的另一个 Reportmanager 版本。或者您没有在 Uses 子句中包含正确的源文件。使用文档。
    • 我认为你错过了我回答的重点。您必须更改TVCLReport 的源代码才能添加我提到的新功能。它还不存在。至于版本,我没有TVCLReport,但是我在ReportManager SourceForge Project上看了最新的源码。
    猜你喜欢
    • 2020-07-10
    • 2020-10-24
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 2023-03-11
    • 2013-01-11
    • 1970-01-01
    相关资源
    最近更新 更多