在另一个线程上渲染 ReportViewer

Posted

技术标签:

【中文标题】在另一个线程上渲染 ReportViewer【英文标题】:Rendering ReportViewer on another thread 【发布时间】:2014-08-21 12:05:21 【问题描述】:

我正在尝试在 ASP .Net 中的另一个线程上呈现 ReportViewer:

    public ActionResult GenerateReport()
    
    var task = Task.Factory.StartNew(() =>
    
        try
        
            using (LocalReport localReport = new LocalReport())
            
                System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + "bin\\" + "Reports.dll");
                using (System.IO.Stream stream = assembly.GetManifestResourceStream("Report.rdlc"))
                


                    localReport.LoadReportDefinition(stream);
                    string mimeType;
                    string encoding;
                    string fileNameExtension;

                    Warning[] warnings;
                    string[] streams;
                    byte[] rendered;

                    //Render the report
                    renderedBytes = localReport.Render(
                        "PDF",
                        deviceInfo,
                        out mimeType,
                        out encoding,
                        out fileNameExtension,
                        out streams,
                        out warnings);

                   Session["Report"] = renderedBytes;
                
            
        
        catch (Exception ex)
        
            Logger.Error("Error", ex);
        
    );

    return new View();
 

但我遇到了这个异常:

Microsoft.Reporting.WebForms.LocalProcessingException:本地报表处理过程中出错。 ---> Microsoft.ReportingServices.ReportProcessing.ReportProcessingException:无法加载表达式宿主程序集。详细信息:用于模拟的令牌无效 - 不能复制。 在 Microsoft.ReportingServices.RdlExpressions.ReportRuntime.ProcessLoadingExprHostException(ObjectType assemblyHolderObjectType,异常 e,ProcessingErrorCode 错误代码) 在 Microsoft.ReportingServices.RdlExpressions.ReportRuntime.LoadCompiledCode(IExpressionHostAssemblyHolder 表达式HostAssemblyHolder,布尔 includeParameters,布尔参数Only,ObjectModelImpl reportObjectModel,ReportRuntimeSetup runtimeSetup) 在 Microsoft.ReportingServices.OnDemandProcessing.Merge.Init (Boolean includeParameters, Boolean parametersOnly) 在 Microsoft.ReportingServices.OnDemandProcessing.Merge.Init(ParameterInfoCollection 参数) 在 Microsoft.ReportingServices.ReportProcessing.Execution.ProcessReportOdp.CreateReportInstance(OnDemandProcessingContext odpContext,OnDemandMetadata odpMetadata,ReportSnapshot 报告快照,合并和 odpMerge) 在 Microsoft.ReportingServices.ReportProcessing.Execution.ProcessReportOdp.Execute(OnDemandProcessingContext& odpContext) 在 Microsoft.ReportingServices.ReportProcessing.Execution.RenderReportOdpInitial.ProcessReport(ProcessingErrorContext errorContext、ExecutionLogContext executionLogContext、UserProfileState&userProfileState) 在 Microsoft.ReportingServices.ReportProcessing.Execution.RenderReport.Execute(IRenderingExtension newRenderer) 在 Microsoft.ReportingServices.ReportProcessing.ReportProcessing.RenderReport(IRenderingExtension newRenderer,DateTime executionTimeStamp,ProcessingContext pc,RenderingContext rc,IChunkFactory yukonCompiledDefinition) 在 Microsoft.Reporting.LocalService.CreateSnapshotAndRender(ReportProcessing repProc、IRenderingExtension 渲染器、ProcessingContext pc、RenderingContext rc、SubreportCallbackHandler subreportHandler、ParameterInfoCollection 参数、DatasourceCredentialsCollection 凭据) 在 Microsoft.Reporting.LocalService.Render(字符串格式,字符串 deviceInfo,字符串分页模式,布尔 allowInternalRenderers,IEnumerable 数据源,CreateAndRegisterStream createStreamCallback) 在 Microsoft.Reporting.WebForms.LocalReport.InternalRender(字符串格式,布尔 allowInternalRenderers,字符串 deviceInfo,PageCountMode pageCountMode,CreateAndRegisterStream createStreamCallback,警告 [] 和警告) --- 内部异常堆栈跟踪结束 --- 在 Microsoft.Reporting.WebForms.LocalReport.InternalRender(字符串格式,布尔 allowInternalRenderers,字符串 deviceInfo,PageCountMode pageCountMode,CreateAndRegisterStream createStreamCallback,警告 [] 和警告) 在 Microsoft.Reporting.WebForms.LocalReport.InternalRender(字符串格式,布尔 allowInternalRenderers,字符串 deviceInfo,PageCountMode pageCountMode,字符串和 mimeType,字符串和编码,字符串和文件名扩展,字符串 [] 和流,警告 [] 和警告) 在 Microsoft.Reporting.WebForms.LocalReport.Render(字符串格式、字符串 deviceInfo、PageCountMode pageCountMode、字符串和 mimeType、字符串和编码、字符串和文件名扩展、字符串 [] 和流、警告 [] 和警告) 在 Web.Controllers.ReportsController()

谢谢,感谢任何帮助

【问题讨论】:

第一个问题(假设这仍然是一个问题):你能在同一个线程上成功运行它吗?) 嗨,它在同一个线程上成功运行。我反编译了 dll 并追踪到这条线被执行了windowsImpersonationContext = WindowsIdentity.Impersonate(IntPtr.Zero);。谢谢 您是否在您的 web.config 中进行任何类型的模拟?您是否在报告中引用了任何其他程序集? 我没有做任何类型的模仿,但 AppPool 的身份是自定义的。在报告中没有其他程序集。它有表达式。 【参考方案1】:

我遇到了同样的问题,但使用的是 WPF 应用程序。

似乎 ReportViewer.RefreshReport 已经在另一个线程中运行了。

只需删除 async / Task,即使您在同一线程/时间刷新它们,它也可以正常工作。

            foreach (ReportViewer r in ListaReportes)
            
                ContentPresenter Presenter = new ContentPresenter();
                Presenter.Width = 200;
                Presenter.Height = 260;
                WindowsFormsHost Host = new WindowsFormsHost();
                Host.Child = r;
                Presenter.Content = Host;
                Miniaturas.Children.Add(Presenter);

                try
                
                    r.RefreshReport();
                 catch(Exception)
                
                
             

此代码添加了许多报告,所有报告同时开始刷新。

【讨论】:

报告应该在任务中生成,因为获取数据的阶段需要很长时间。在示例代码中不是简化代码的那个阶段。 @amit 这取决于您使用的报告类型:如果 RDL 数据由报告本身加载,如果您使用 RDLC,则可以在 任务上加载数据 然后将其传递给报表,但 RefreshReport 必须在主线程中调用(RefreshREport 自己在另一个线程上运行)。

以上是关于在另一个线程上渲染 ReportViewer的主要内容,如果未能解决你的问题,请参考以下文章

QT opengl多线程实现原理

Flask:在另一个页面上使用WTForm,而不是渲染表单本身

任务在另一个线程 .NET 上异步运行

在另一个线程上接收的套接字上触发 EAGAIN

C ++如何等待在另一个线程上执行的方法然后主线程完成(VS2010)

在另一个线程上调用非静态类函数