I have a Camera class that produces very large images at a high FPS that require processing by a ImageProcessor class. I also have a WPF Control, my View, that displays this information. I need each of these components needs to run on it’s own thread so it doesn’t lock up the processing.
Method 1) Camera has an Action<Image> ImageCreated that ImageProcessor subscribes to. ImageProcessor has an Action<Image, Foo> ImageCreated that contains an altered Image and Foo results for the View to show.
Method 2) Camera has a threadsafe (using locks and monitors) ProducerConsumer to which it produces Images, and ImageProcessor waits and Consumes. Same story for the View.
Method 2 is nice because I can create and manage my own threads.
Method 1 is nice because I have have multiple ImageProcessors subscribed to the Camera class. But I’m not sure who’s thread is doing the heavyweight work, or if Action is wasting time creating threads. Again these images come in many times per second.
I’m trying to get the images to my View as quickly as possible, without tying up processing or causing the View to lock up.
Thoughts?
Unless you do it yourself, using Method 1) does not introduce any multithreading. Invoking an action (unless you call
BeginInvoke) does so synchronously, just like any normal method call.I would advocate Method 2). There is no need to tie it to one single consumer. If you use this queue as a single point of contact between X cameras and Y processors, you’ve decoupled the cameras from the processors and could modify the value of X and Y independently.
EDIT
At the risk of being accused of blog spam here, I remembered that I wrote a component that’s similar (if not an exact match) for what you’re looking for awhile ago. See if this helps:
ProcessQueue
The gist of it is that you provide the queue with a delegate that can process a single item–in your case,
Image–in the constructor, then callStart. As items are added to the queue usingEnqueue, they’re automatically dispatched to an appropriate thread and processed.For example, if you wanted to have the image move Camera->Processor->Writer (and have a variable number of each), then I would do something like this:
You could vary the number of threads in
cameraQueue(which controls the image processing) andprocessorQueue(which controls writing to disk) by usingSetThreadCount.Once you’ve done that, you would just call
cameraQueue.Enqueue(image)whenever a camera captured an image.