Perform Multi-Threaded OCR
This topic provides some background information about using ImageGear OCR in a multi-threaded application and walks you through creating a new multi-threaded application using OCR.
About Using Recognition in a Multi-Threaded Application
The Recognition API can be used in a multi-threaded application. However, it is generally the application's responsibility to ensure that the different recognition activities (e.g., pre-processing, decomposition, recognition, etc.) occur sequentially for any given image or page.
Multiple instances of the ImGearRecognition object are now supported in a single process. While all instances of this object will access the same underlying native Recognition engine, each instance operates on its own set of pages and documents.
Each instance can use the shared global collection of Recognition settings if instantiated with the default constructor. This means that changing settings (e.g.,
ImGearRecOutputManager.Format) in one instance will affect all other instances using the global settings. To isolate the Recognition settings for each instance, use the overloaded constructor,
ImGearRecognition(bool). This will force each instance to use its own collection of unique settings.
Using multiple instances of the ImGearRecognition object in separate threads enables the application to perform recognition activities on different images and pages in parallel. However, it is important to remember that for each page, the recognition process must occur sequentially, meaning that a page must first be imported and pre-processed before it can be recognized and exported. Also, access to the underlying formatted output module is synchronized, so only one instance can export to a formatted output document at a time.
No re-entrance is allowed within the same thread. This can occur when the API is firing an event. When the focus of control is in the application-defined event handler, no methods of the
Recognition API can be called.
Memory Usage Best Practices
The ImageGear Recognition assembly provides you with the ability to perform recognition activities on multiple images in parallel. However, you will want to ensure that the amount of memory being consumed by this process does not exceed the limitations of the system. This can occur if, for example, all pages of a large PDF are opened at once and then sent to the Recognition assembly for processing.
The following points should always be considered when using the Recognition API, but especially when calling it within multiple threads or when large images are to be recognized:
- The ImGearRecognition.ImportPage method will create a copy of the imported ImGearRasterPage that will be used exclusively by the recognition engine. Care should be taken to account for this memory overhead in your application.
- The Recognition API uses native binaries and therefore inherits from the IDisposable interface. The Dispose methods of the recognition objects should be called as soon as the objects are no longer needed in the application.
- ImageGear will not monitor memory usage for you. Failure to do so can result in Out Of Memory Exceptions in high-stress applications using multiple threads and/or large images.
An alternative to the “all-at-once” processing style mentioned above is a processing technique where smaller chunks of images are opened, processed, exported and closed in an assembly line style. This technique ensures that only a specified number of images are opened and being processed at one time, keeping a consistent and manageable memory footprint throughout the process.
The following walkthrough describes this technique using the System.Threading.Tasks.Parallel class included in the .NET 4.0 Framework. In this walkthrough, you will create a .NET 4 Windows application that processes all pages of a PDF file while ensuring a controlled memory footprint throughout the task.
Creating the Project
This section describes how to create the project for this sample:
- Start Visual Studio and create a new Windows Forms Application project in C# named ParallelSample.
- In Visual Studio, add the following ImageGear references to your project:
- ImageGear24.Core
- ImageGear24.Evaluation
- ImageGear24.Formats.Advanced
- ImageGear24.Formats.Common
- ImageGear24.Formats.Pdf
- ImageGear24.Recognition
- ImageGear24.Windows.Forms
Creating the Page Processor Class
This section describes how to create the class that will perform the parsing and recognition of the PDF file using multiple threads:
- In Visual Studio, add a new class to the ParallelSample project called PageProcessorTest.
- Add the following using statements to the top of the class file. This code imports the proper types for use in the class.
- Add the following code to initialize a new instance of the class. This code sets up licensing, initializes the ImageGear Formats assembly and adds the required format filters. In this sample, we are only supporting the PDF and PostScript formats:
- Add the following code to create a private method that processes a chunk of pages. This code works on an array of ImGearRecPage objects to pre-process and recognize them in parallel. After each page has been processed, the results are added to the output document and the pages used for recognition are disposed to free up memory for the next chunk.
- Add the following code to create a public method called Process. This code initializes the ImageGear Recognition assembly, creates the output document and calls the ProcessPageChunk method created in Step 3 (above) for each chunk until all pages are processed. In this example, a maximum of 4 pages will be processed in parallel. This value can change in your situation depending upon the number of cores and threads your CPU supports.
Calling the Page Processor Class
This section describes how to call the PageProcessorTest class that you created above:
- Create your own User Interface to enable the user to select a PDF file to process. This example assumes that a file has been selected and valid filename is available.
- Add the following code to call the PageProcessorTest class you created: