Printing Performance with Split Documents

Hi,

I am printing off a batch of letters with Aspose.Words. The letters are Duplex and want to be printed on Headed Paper but specifically I want to print on the front AND BACK of the headed paper. I’m printing 400 different document formats so changing the documents isn’t an option.

So what I am doing is:
For each Section in the document set the PageSetup.FirstPage and OtherPages to Tray 1 (where the Headed Paper is) then printing page 1 & 2, then setting the PageSetup.FirstPage and OtherPages to Tray 2 (where the Continuation Paper is) and printing the rest of the document.

This works well, but it is slow.
So I thought Id multithread it, which improved the performance brilliantly. But when multithreading the printing I cant guarantee the order of the documents, so Page1&2 of Document 2 is likely to come out before the other pages of Document 1.

Can you think of any way around this. can I print pages 1&2 to a file and then add the other pages or something like that.
Can I use some sort of clever PostScript rendering?
If I synclock the threads then it defeats the object of multithreading. Would UpdatePageLayout multithreaded make a significant difference? If I change the paper source will this rendering model need updating anyway?

Its an interesting problem. Have you got any ideas?

@TRobson,

We are checking this scenario and will get back to you soon.

What about using AsposeWordsPrintDocument.Print to produce the document. This might give me more control over individual pages, but is this safe in a multithreaded environment? And can I disable the Print Progress Dialogue.

I remember how to disable the Print Progress Dialog. Changing the default AsposeWordsPrintDocument.PrintController to a new System.Drawing.Printing.StandardPrintController.

What about multithreading and: AsposeWordsPrintDocument.Print()

@TRobson,

Yes, it supports multithreading.

Also, the idea to use multithreading for building layout sounds really good. The UpdatePageLayout method is called upon printing. So, you have to do multithreading on UpdatePageLayout method with applied settings (the layout model will be created) and then run your printing job in one thread.

Please try these options and let us know how it goes on your end?

Ok, it looks to me like using Aspose.Words.Rendering.AsposeWordsPrintDocument and printing page by page will give me control of the PaperSource perfectly.
Is there a similar pattern I can use for PDFs? I can see there used to be a PrintController in the Aspose.Pdf.Generator namespace but that isn’t there anymore.

@TRobson

We are afraid that, currently you may not control PaperSource while printing a PDF document. However, we have logged an investigation ticket with ID PDFNET-45277 in our issue management system for further investigations. The ticket ID has been linked with this thread so that you will receive notification as soon as the ticket is resolved.

We are sorry for the inconvenience.

Actually: You have a PdfQueryPageSettings event on the Aspose.Pdf.Facades.PdfViewer that you can override to set the PaperSource in a very similar pattern. I’ve tested this and it works perfectly.

@TRobson

Thank you for your kind feedback.

We are glad to know that things have started working in your environment. You have managed to make it work using Facades approach. We will investigate under the logged issue if same requirements can be achieved using Document Object Model (DOM) approach. We will let you know if we have any further updates regarding this issue.

Please keep using our API and in event of any further query, please feel free to ask.

@TRobson

Printing facilities of the Aspose.PDF for .NET library are represented by the Aspose.Pdf.Facades.PdfViewer class. It exposes the PdfViewer.PdfQueryPageSettings event that allows to set individual page settings, including a paper source.

For an example of using the PdfViewer.PdfQueryPageSettings please refer to the following:

public static void Print(string inputFile, string printerName, int duplexMode, int firstTray, int followerTray)
{
    _firstTray = firstTray;
    _followerTray = followerTray;

    PdfViewer viewer = new PdfViewer();
    Aspose.Pdf.Printing.PrinterSettings settings = new Aspose.Pdf.Printing.PrinterSettings();
    Aspose.Pdf.Printing.PageSettings pageSettings = new Aspose.Pdf.Printing.PageSettings();
    PrintDocument doc = new PrintDocument();

    viewer.OpenPdfFile(inputFile);

    settings.PrinterName = doc.PrinterSettings.PrinterName;

    if (ConverterConfig.Instance != null)
        viewer.Resolution = ConverterConfig.Instance.PdfSettings.PdfPrintResolution;

    PrintSettings = settings;

    if (!printerName.IsNullOrEmpty())
        settings.PrinterName = printerName;

    if ((duplexMode == 1 || duplexMode == 2 || duplexMode == 3) && doc.PrinterSettings.CanDuplex)
        settings.Duplex = duplexMode == 1 
            ? Aspose.Pdf.Printing.Duplex.Simplex
            : duplexMode == 2
                ? Aspose.Pdf.Printing.Duplex.Vertical
                : Aspose.Pdf.Printing.Duplex.Horizontal;

    currentPageNumber = 1;
    // Subscribe to the PdfQueryPageSettings event to pass customized settings for each page
    viewer.PdfQueryPageSettings += new PdfQueryPageSettingsEventHandler(doc_QueryPageSettings);

    viewer.PrintDocumentWithSettings(pageSettings, settings);

}

static void doc_QueryPageSettings(object sender, PdfQueryPageSettingsEventArgs e, PdfPrintPageInfo info)
{
    currentPageNumber++;
    foreach (System.Drawing.Printing.PaperSource source in PrintSettings.PaperSources)
    {
        if (source.RawKind == _firstTray)
        {
            e.PageSettings.PaperSource = source.ToAsposePaperSource();
        }
    }

    if (currentPageNumber > 1)
    {
        foreach (System.Drawing.Printing.PaperSource source in PrintSettings.PaperSources)
        {
            if (source.RawKind == _followerTray)
            {
                e.PageSettings.PaperSource = source.ToAsposePaperSource();
            }
        }
    }
}

Also, if the you prefer to work with the PrintDocument directly, you may use the Aspose.Pdf.PrintController class. For an example of changing page settings with the PrintController, please refer to code snippets:

internal class Class2
{
    internal void PDFNEWNET_45624()
    {
        var pdfLicence = new Aspose.Pdf.License();
        pdfLicence.SetLicense("Aspose.Total.NET.lic");
        string outFile = "C:\\Test\\45624.pdf";
        var doc = new PrintDocument();
        doc.PrintPage += new PrintPageEventHandler(mPrintDoc_PrintPage);
        // Subscribe to the PrintDocument.QueryPageSettings event to set individual page settings for every page
        doc.QueryPageSettings += new QueryPageSettingsEventHandler(mPrintDoc_QueryPageSettings);
        var printController = new Aspose.Pdf.PrintController();
        printController.FileName = outFile;
        doc.PrintController = printController;
        doc.Print();
    }

    private void mPrintDoc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
    {
        e.Graphics.DrawRectangle(new Pen(System.Drawing.Color.Red), 0, 0, 100, 100);
        e.Graphics.FillEllipse(new SolidBrush(System.Drawing.Color.Blue), 100, 100, 200, 200);
    }

    private void mPrintDoc_QueryPageSettings(object sender, QueryPageSettingsEventArgs e)
    {
        e.PageSettings.PaperSize = new System.Drawing.Printing.PaperSize("A4", 10, 5);
        e.PageSettings.Margins = new System.Drawing.Printing.Margins(0, 0, 0, 0); // Default margins of the Aspose.Pdf.PrintController are (72, 72, 72, 72)
    }
}

If you want to set the same page settings for the whole document, you may use the PrintDocument.DefaultPageSettings property instead:

internal class Class2
{
    internal void PDFNEWNET_45624()
    {
        var pdfLicence = new Aspose.Pdf.License();
        pdfLicence.SetLicense("Aspose.Total.NET.lic");
        string outFile = "C:\\Test\\45624.pdf";
        var doc = new PrintDocument();
        doc.PrintPage += new PrintPageEventHandler(mPrintDoc_PrintPage);
        // Use the PrintDocument.DefaultPageSettings property to set page settings for the whole document
        doc.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("A4", 10, 5);
        doc.DefaultPageSettings.Margins = new System.Drawing.Printing.Margins(0, 0, 0, 0); // Default margins of the Aspose.Pdf.PrintController are (72, 72, 72, 72)
        var printController = new Aspose.Pdf.PrintController();
        printController.FileName = outFile;
        doc.PrintController = printController;
        doc.Print();
    }

    private void mPrintDoc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
    {
        e.Graphics.DrawRectangle(new Pen(System.Drawing.Color.Red), 0, 0, 100, 100);
        e.Graphics.FillEllipse(new SolidBrush(System.Drawing.Color.Blue), 100, 100, 200, 200);
    }
}

Please also note that your desired page size cannot be less than page margins summary size, otherwise you’ll get an exception saying that there is not enough space on the page.

There is a bug in a library - Margins set in a page settings are not applied, the Aspose.Pdf.PrintController always uses its default margins of (72, 72, 72, 72). This bug is fixed in the 24.7 version.

In versions prior to 24.7 please use the following formulas to define the page size:

e.PageSettings.PaperSize = new System.Drawing.Printing.PaperSize("A4", 72 + 72 + desiredWidth, 72 + 72 + desiredHeight);