Developers / Export Reports / Manage Asynchronous Report Rendering
Manage Asynchronous Report Rendering

ActiveReports provides a number of possibilities to control the export process, which can help you create more responsive applications. In this topic, we discuss common use cases of asynchronous or long-running report rendering:

Display Progress Information

Let's see how you can have displayed the export rendering progress information, using a WinForms Viewer application. As an example, we will take the Export sample that you can access by following this link - https://github.com/activereports/Samples19/tree/main/API/PageAndRDLX/Export.

The rendering progress information can be displayed for PDF, Image, HTML, and Excel exports at the report rendering.

Note: The progress information is not shown if the report is exported with the Pagination property set to False (Image, Excel Rendering Extensions) or with the Mode property set to Galley (HTML Rendering Extension).
  1. Open the Export sample project.
  2. From the Visual Studio toolbox, drag the Label control onto the Form.
  3. Add this code into the Form.
    Visual Basic.NET code
    Copy Code
    Private Async Sub ExportAsync(ByVal report As PageReport, ByVal renderingExtension As IRenderingExtension, ByVal outputProvider As StreamProvider, ByVal settings As NameValueCollection)
       labelExport.Text = "Export started..."
       Dim control = Me 
       Dim progress = New Progress(Of ProgressInfo)(Sub(progressInfo)
          control.BeginInvoke(New MethodInvoker(Sub()
             labelExport.Text = If(progressInfo.IsLast = True, "Export is finished." , $"Exported {progressInfo.PageNumber} pages.")
          End Sub))
       End Sub)
       
       await Task.Run(Sub()
          Try
             report.Document.Render(renderingExtension, outputProvider, settings, False, False, CancellationToken.None, progress)
          Catch e as Exception
          End Try
       End Sub)
    End Sub                              
    
    C# code
    Copy Code
    private async void ExportAsync(PageReport report, IRenderingExtension renderingExtension, StreamProvider outputProvider, NameValueCollection settings)
    {
       labelExport.Text = "Export started...";
       var control = this;
       var progress = new Progress<ProgressInfo>(progressInfo =>
       {
          control.BeginInvoke(new MethodInvoker(() =>
          {
             labelExport.Text = progressInfo.IsLast ? "Export is finished." : $"Exported {progressInfo.PageNumber} pages.";
                
          }));
       });
       await Task.Run(() =>
       {
          try
          {
             report.Document.Render(renderingExtension, outputProvider, settings, false, false, CancellationToken.None, progress);
          }
          catch
          {
             // ignored
          }
       });
    }                                
    
       
  4. Run the project.
  5. In the Export form, select PDF, Image, HTML, or Excel export type.
  6. Click the Export button and see the progress information in the new label.
    Click the Export button in Export Sample Report

Cancel Report Rendering

You can cancel the report rendering or export by using the following code.

Visual Basic.NET code
Copy Code
Dim _cancellationTokenSource

Private Async Sub ExportAsync(ByVal report As PageReport, ByVal renderingExtension As IRenderingExtension, ByVal outputProvider As FileStreamProvider, ByVal settings As NameValueCollection)
   _cancellationTokenSource = New CancellationTokenSource()
   exportButton.Text = "Cancel"
   RemoveHandler exportButton.Click, AddressOf exportButton_Click
   AddHandler exportButton.Click, AddressOf CancelExport
   Await Task.Run(Sub()
      Try
         report.Document.Render(renderingExtension, outputProvider, settings, False, False, _cancellationTokenSource.Token)
      Catch unusedOperationCanceledException As OperationCanceledException
      End Try
   End Sub)
   If _cancellationTokenSource.IsCancellationRequested Then MessageBox.Show("Export was cancelled", "Export", MessageBoxButtons.OK, MessageBoxIcon.Information)
   _cancellationTokenSource.Dispose()
   _cancellationTokenSource = Nothing
   RemoveHandler exportButton.Click, AddressOf CancelExport
   AddHandler exportButton.Click, AddressOf exportButton_Click
   exportButton.Text = "Export"
End Sub

Private Sub CancelExport(ByVal sender As Object, ByVal e As EventArgs)
   _cancellationTokenSource?.Cancel()
End Sub 
C# code
Copy Code
private CancellationTokenSource _cancellationTokenSource;                 
private async void ExportAsync(PageReport report, IRenderingExtension renderingExtension, FileStreamProvider outputProvider, NameValueCollection settings)
{
   _cancellationTokenSource = new CancellationTokenSource();
   exportButton.Text = "Cancel";
   exportButton.Click -= exportButton_Click;
   exportButton.Click += cancelExport;
     
   await Task.Run(() =>
   {
      try
      {
         report.Document.Render(renderingExtension, outputProvider, settings, false, false, _cancellationTokenSource.Token);
      }
      catch (OperationCanceledException)
      {
      }
   });
     
   if (_cancellationTokenSource.IsCancellationRequested)
       MessageBox.Show("Export was cancelled", "Export", MessageBoxButtons.OK, MessageBoxIcon.Information);
   _cancellationTokenSource.Dispose();
   _cancellationTokenSource = null;
   exportButton.Click -= cancelExport;
   exportButton.Click += exportButton_Click;
   exportButton.Text = "Export";
}
     
private void cancelExport(object sender, EventArgs e)
{
   _cancellationTokenSource?.Cancel();
}        

Information Logging

To log information on the report rendering, add Trace Listeners. As an example, modify the ExportAsync function as follows.

Visual Basic.NET code
Copy Code
Private Async Sub ExportAsync(ByVal report As PageReport, ByVal renderingExtension As IRenderingExtension, ByVal outputProvider As StreamProvider, ByVal settings As NameValueCollection)
   labelExport.Text = "Export started..."
   Dim control = Me 
   Dim progress = New Progress(Of ProgressInfo)(Sub(progressInfo)
      control.BeginInvoke(New MethodInvoker(Function()
         labelExport.Text = If(progressInfo.IsLast = True, "Export is finished." , $"Exported {progressInfo.PageNumber} pages.")
         Trace.TraceInformation($"Exported {progressInfo.PageNumber} pages.")
      End Function))
   End Sub)
   await Task.Run(Sub()
      Try
         Dim traceWriter = New TextWriterTraceListener("TextWriterOutput.log", "myListener")
         Trace.Listeners.Clear()
         Trace.Listeners.Add(traceWriter)
         report.Document.Render(renderingExtension, outputProvider, settings, False, False, CancellationToken.None, progress)
         Trace.Flush()
         Trace.Listeners.Clear()
      Catch e as Exception
      End Try
   End Sub)
End Sub 
C# code
Copy Code
private async void ExportAsync(PageReport report, IRenderingExtension renderingExtension, StreamProvider outputProvider, NameValueCollection settings)
{
   labelExport.Text = "Export started...";
   var control = this;
   var progress = new Progress<ProgressInfo>(progressInfo =>
   {
      control.BeginInvoke(new MethodInvoker(() =>
      {
         labelExport.Text = progressInfo.IsLast ? "Export is finished." : $"Exported {progressInfo.PageNumber} pages.";
         Trace.TraceInformation($"Exported {progressInfo.PageNumber} pages.");
      }));
   });
   await Task.Run(() =>
   {
      try
      {
         var traceWriter = new TextWriterTraceListener("TextWriterOutput.log", "myListener");
         Trace.Listeners.Clear();
         Trace.Listeners.Add(traceWriter);
         report.Document.Render(renderingExtension, outputProvider, settings, false, false, CancellationToken.None, progress);
         Trace.Flush();
         Trace.Listeners.Clear();  
      }
      catch
      {
         // ignored
      }
   });
}