Once you've got your multicore machine, I bet you've been thinking about whether other tools are able to use these cores. Modern software should utilize every possibility to work faster and scale together with the system it’s designed for.
ApitronPDF Rasterizer was designed to get the most out of the .NET platform and also with ability to use as many CPU cores as its host system has. It was designed from the ground up to take advantage of multicore systems and parallel execution. Almost every operation that could benefit from it was parallelized.
The code
I've modified our sample included in product package in order to show you how the page by page PDF document rendering can be transformed to multithreaded. PDF specification was used as a test file.
///<summary>
/// Render PDF file using ThreadPool
///</summary>
privatestaticvoid Main(string[] args)
{
// open and load the file
using (FileStreamfs = newFileStream(@"..\..\..\Documents\pdf32000_2008.pdf", FileMode.Open))
{
// create rendering settings instance here, it can be used later for rendering cancellation if needed
RenderingSettings renderingSettings = newRenderingSettings();
// this object represents a PDF document
Document document = newDocument(fs);
ManualResetEvent[] completionEvents = newManualResetEvent[document.Pages.Count];
// process and save pages one by one
for (int i = 0; i < document.Pages.Count; i++)
{
int pageIndex = i;
completionEvents[pageIndex] = newManualResetEvent(false);
ThreadPool.QueueUserWorkItem((state) =>
{
Page currentPage = document.Pages[pageIndex];
// we use original page's width and height for image as well as default rendering settings
using ( Bitmapbitmap = currentPage.Render( (int)currentPage.Width, (int)currentPage.Height, renderingSettings ))
{
bitmap.Save(string.Format("{0}.png", pageIndex), ImageFormat.Png);
}
completionEvents[pageIndex].Set();
});
}
// sync at this point and wait for all events to be set,
// since WaitHandle.WaitAll supports only 64 handles we can't use it here
foreach (ManualResetEventmanualResetEvent in completionEvents)
{
manualResetEvent.WaitOne();
}
// preview first rendered page
Process.Start("0.png");
}
}
Same code but using Tasks
///<summary>
/// Render PDF file using Tasks
///</summary>
privatestaticvoid Main(string[] args)
{
// open and load the file
using (FileStreamfs = newFileStream(@"..\..\..\Documents\pdf32000_2008.pdf", FileMode.Open))
{
// create rendering setting instance here, it can be used later for rendering cancellation if needed
RenderingSettings renderingSettings = newRenderingSettings();
// this object represents a PDF document
Document document = newDocument(fs);
Task[] tasks = newTask[document.Pages.Count];
// process and save pages one by one
for (int i = 0; i < document.Pages.Count; i++)
{
int pageIndex = i;
tasks[pageIndex] = newTask(()=>
{
Page currentPage = document.Pages[pageIndex];
// we use original page's width and height for image as well as default rendering settings
using (Bitmapbitmap = currentPage.Render((int)currentPage.Width, (int)currentPage.Height, renderingSettings))
{
bitmap.Save(string.Format("{0}.png", pageIndex), ImageFormat.Png);
}
});
tasks[pageIndex].Start();
}
// sync at this point and wait for all tasks to complete
Task.WaitAll(tasks);
// preview first rendered page
Process.Start("0.png");
}
}
Images
Start of the rendering, you clearly see how all 4 available CPU cores begin their work
![]() |
Rendering begins Rendering in progress, all cores are busy |
![]() |
Rendering in progress |
Cancellation
While it’s important to perform multithreaded rendering it’s also important to handle rendering cancellation in most convenient and easy way.
Thread.Abort() usage is not a recommended approach, and in case of Tasks even CancellationToken usage can only affect rendering that is not yet started. But we’ve designed our rendering engine to handle this situation and it’s possible to cancel rendering while it’s actually running. To do this just call CancelRendering() method using the RenderingSettings instance that was passed to rendering routine. And that’s it.
If you have any questions don’t hesitate to contact us and we’ll do our best to help you. As always we welcome any feedback.