Most developers assume that WPF is only used for generating the UI of your application. But it also proves a great tool for generating simple reports from worker threads. The following workflow demonstrates how easy it is…
1. XAML Design
Use your existing tools such as Visual Studio or KAXAML to create your report layout using the usual WPF controls such as Grid, StackPanel, TextBlock and so forth. If your one of the few developers that is familiar with Expression Blend then you should be able to create a nice looking report really quickly. Use data binding to get the actual values that will be needed when the report is generated.
2. Worker Thread
Use a worker thread to load in the XAML and load in the current data values from a database or other source. Set the DataContext at the root of the XAML to the object that provides your report values.
3. Render and Save
Use the RenderTargetBitmap to render the XAML to a bitmap that can then be saved in whatever format you prefer.
4. Prevent Memory Leak
After following the first three steps you will run your reports and notice that you are slowing leaking memory. Here is a minimal console application to demonstrate the leak occurring…
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(() => ThreadRun());
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
Console.WriteLine("Total Memory = {0}", GC.GetTotalMemory(true));
}
Console.ReadLine();
}
static void ThreadRun()
{
Grid g = new Grid();
TextBlock tb = new TextBlock();
tb.Text = "Hello World!";
g.Children.Add(tb);
}
WPF makes use of a thread specific Dispatcher instance for event handling. Even though our example has no user interaction and does not even render it still causes a dispatcher instance to be created for the thread. If you create a WPF control then you cause a dispatcher to be created if not already present.
Some WPF controls also use the dispatcher for memory management although that is not the case for the simple example we have with a Grid and TextBlock. Whenever a thread has a dispatcher you must close it down gracefully to prevent a memory leak. Here is the updated code with the dispatcher shutdown code added.
static void ThreadRun()
{
Grid g = new Grid();
TextBlock tb = new TextBlock();
tb.Text = "Hello World!";
g.Children.Add(tb);</code>
// Allow dispatcher to process any waiting delegates as it shutsdown
Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.SystemIdle);
Dispatcher.Run();
}
Now our example runs without leaking, once it has settled down in usage from the first iteration.
References
MSDN – Thread
MSDN – Dispatcher


Oh my goodness! Impressive article dude! Many
thanks, However I am experiencing problems with
your RSS. I don’t understand the reason why I am unable to subscribe to it.
Is there anyone else getting the same RSS issues?
Anybody who knows the solution will you kindly respond?
Thanx!!