Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronous async await method to generate pdf

I decided to convert the method that generates a PDF to asynchronous call. The asynchronous call doesn't produce the requested PDF and I have no idea why this is happening

The client who calls the async operation is as follows:

public QuotationResponse CreateQuotation(IQuotation quotation)
{
    ...
    // Create Quotation PDF
    _pdfWriter.GeneratePdfAsync(response);
    return response;
}

The class responsible for generating the PDF is the following:

public class Writer
{
   //... other class methods
   public async Task GeneratePdfAsync(QuotationResponse response)
   {
       await new Task(() =>
       {
            var currentPath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
            var formFile = Path.Combine(currentPath, Settings.Default.QUOTATION_TEMPLATE_PATH);
            var newFile = Path.Combine(currentPath, Settings.Default.QUOTATION_PDF_PATH);
            var reader = new PdfReader(formFile);
            using (PdfStamper stamper = new PdfStamper(reader, new FileStream(newFile, FileMode.Create)))
            {
                ....
                // flatten form fields and close document
                stamper.FormFlattening = true;
                stamper.Close();
            }
       });
   }
}

I suspect that I'm not doing something right with the async - await operation but don't know what. Could you please assist?


1 Answers

You should never use the Task constructor. Ever. It has absolutely no valid use cases. At all. For any kind of approach to any kind of problem. Full details on my blog.

Since there is no asynchronous work to do, you should just use synchronous methods:

public class Writer
{
  //... other class methods
  public void GeneratePdfAsync(QuotationResponse response)
  {
    var currentPath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
    ...
  }
}

If you want to call this from a GUI application and don't want to block the UI thread, then you can call it on a background thread by using await Task.Run, as such:

QuotationResponse response = await Task.Run(() => CreateQuotation(quotation));
like image 179
Stephen Cleary Avatar answered May 20 '26 14:05

Stephen Cleary