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>
private static void Main(string[]
args)
{
// open and load the file
using (FileStream
fs = new FileStream(@"..\..\..\Documents\pdf32000_2008.pdf",
FileMode.Open))
{
// create rendering settings instance here, it can be used
later for rendering cancellation if needed
RenderingSettings renderingSettings = new RenderingSettings();
// this object represents a PDF document
Document document = new
Document(fs);
ManualResetEvent[] completionEvents = new ManualResetEvent[document.Pages.Count];
// process and save pages one by one
for (int i = 0; i
< document.Pages.Count; i++)
{
int pageIndex = i;
completionEvents[pageIndex] = new ManualResetEvent(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 ( Bitmap
bitmap = 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 (ManualResetEvent
manualResetEvent in completionEvents)
{
manualResetEvent.WaitOne();
}
// preview first rendered page
Process.Start("0.png");
}
}
Same code but using Tasks
/// <summary>
/// Render PDF file using Tasks
/// </summary>
private static void Main(string[]
args)
{
// open and load the file
using (FileStream
fs = new FileStream(@"..\..\..\Documents\pdf32000_2008.pdf",
FileMode.Open))
{
// create rendering setting instance here, it can be used
later for rendering cancellation if needed
RenderingSettings renderingSettings = new RenderingSettings();
// this object represents a PDF document
Document document = new
Document(fs);
Task[] tasks = new
Task[document.Pages.Count];
// process and save pages one by one
for (int i = 0; i < document.Pages.Count; i++)
{
int pageIndex = i;
tasks[pageIndex] = new Task(()=>
{
Page currentPage =
document.Pages[pageIndex];
// we use original page's width and height for
image as well as default rendering settings
using (Bitmap
bitmap = 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.
No comments:
Post a Comment