TX Text Control .NET for WPF

Performance Best Practices

Topic

Before tuning a WPF application with TX Text Control, check the decisions that matter most: whether document work leaves the dispatcher free, whether every ServerTextControl is disposed, in which format documents live while they change, and whether the application waits for a printer when it starts. The table below lists these and the other performance measures with their effect, as Text Control has measured or described it, and the page with the code.

At a Glance

PracticeEffectRead
Run long document work on other threadsThe window stays responsive, and the user can cancelBackground Operations
Touch WPF elements only on the UI threadNo cross-thread exceptions; results reach the editor through await or the DispatcherDispatcher and UI Thread Access
Use ServerTextControl for documents the user doesn't seeNo undo history and no rendering for the screenUsing ServerTextControl in Desktop Applications
Dispose every ServerTextControlCreate keeps working; Windows allows 10,000 USER and 10,000 GDI handles per processMemory Usage and Resource Disposal
Insert formatted text with Selection objectsAbout twice as fast as inserting, selecting and formatting, in a server benchmarkLarge Documents
Switch off IsUndoEnabled while code builds a document in the editorSaves time and memory, according to the referenceUndo and Redo
Keep documents in the TX Text Control format until they're finalNo conversion when loading and savingDocument Loading and Conversion
Convert a batch with one ServerTextControl0.46 seconds for one large file, 0.18 seconds per file in a batch of 400Large Documents
Split long merge blocksTwo blocks merged faster than one block with the same rowsMail Merge Performance
Merge large batches in separate processes100 merges in 14 instead of 45 seconds on 16 coresMail Merge Performance
Compress images in PDF files14.68 MB down to 1.48 MB in a test documentLarge Documents
Set a default formatting printerNo wait for a slow printer when a control is createdStart Without Waiting for a Printer
Measure your own workloadEvery benchmark depends on its documents and hardwareMeasure Your Own Workload

Start Without Waiting for a Printer

The layout of a document follows the device named by FormattingPrinter, so that the screen shows what the printer prints. That device is asked for information whenever a control is created, and a printer that answers slowly, such as a network printer in energy saving mode, delays the start of the window. Even with FormattingPrinter set to "Display", TX Text Control contacts the default printer while it initializes.

Since version 30.0, the static property DefaultFormattingPrinter sets the device before the first instance exists; TX Text Control then doesn't access any other printer or the print spooler. In a WPF application, set it when the application starts, in App.xaml.cs:

using System.Windows;

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        // Before the window with the TextControl is created
        TXTextControl.WPF.TextControl.DefaultFormattingPrinter = "Display";
        TXTextControl.ServerTextControl.DefaultFormattingPrinter = "Display";

        base.OnStartup(e);
    }
}

"Display" is a screen device that formats text the same way on every machine. Documents that must match the output of one particular printer exactly need that printer as formatting device instead. The blog article Initialize Text Control Without a Printer (Completely) introduces the property with a Windows Forms example and describes it for ServerTextControl instances in WPF applications as well; the WPF TextControl has the same static property. DefaultFormattingPrinter has no page in the reference.

Measure Your Own Workload

The numbers in the table were measured with Text Control's documents and hardware, mostly with TX Text Control .NET Server, and not every article names the hardware. Measure the steps of your own documents before you change code. The following handler times the creation, loading, merging and saving of the files of Mail Merge Performance, on a background thread as in your application:

using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using TXTextControl;
using TXTextControl.DocumentServer;

private async void Measure_Click(object sender, RoutedEventArgs e)
{
    string report = await Task.Run(() =>
    {
        string json = File.ReadAllText("invoice.json");
        Stopwatch stopwatch = Stopwatch.StartNew();

        using (ServerTextControl tx = new ServerTextControl())
        {
            tx.Create();
            long create = stopwatch.ElapsedMilliseconds;

            stopwatch.Restart();
            tx.Load("invoice.docx", StreamType.WordprocessingML, new LoadSettings
            {
                ApplicationFieldFormat = ApplicationFieldFormat.MSWord,
                LoadSubTextParts = true
            });
            long load = stopwatch.ElapsedMilliseconds;

            stopwatch.Restart();
            using (MailMerge mailMerge = new MailMerge { TextComponent = tx })
            {
                mailMerge.MergeJsonData(json);
            }
            long merge = stopwatch.ElapsedMilliseconds;

            stopwatch.Restart();
            tx.Save("invoice.pdf", StreamType.AdobePDF);
            long save = stopwatch.ElapsedMilliseconds;

            return $"Create: {create} ms\nLoad: {load} ms\nMerge: {merge} ms\nSave: {save} ms";
        }
    });

    MessageBox.Show(this, report, "Measurement");
}

The code works as follows:

  • Stopwatch of System.Diagnostics measures each step; Restart sets it back to zero before the next one.
  • The work runs in Task.Run, like the background code it stands for, and returns its report as a string, which the handler shows on the UI thread.
  • The first run includes one-time work of the process. Text Control's benchmarks warm up or average several runs, so run the measurement several times and compare the later results.

Measure with release builds, on computers like those of your users and with the documents they create.

Next Steps