Hi,
I am working with 4 genie nano cameras and I need to pull all the images together to process them as 1. I have used for this code BackgroundWorker to grab all the images using Device.Stream.Wait() on each device. Each device is being triggered from PLC
Is there a better way to do that?
I didn’t find any examples and using the GettingStarted async await code caused big delay when displaying all 4 images in WPF application (when running continuously and even with trigger).
I am not very experienced with concurrency.
Thanks!
Hi @piotrM,
can you tell a bit more about your application? Are the 4 cameras triggered synchronously or in a short time span? Can you ensure that you have no transfer errors (see statistics in the getting started). Transfer errors and corrupt frames can look like long delays or “stuttering” displays.
Other than that I would advice agains background workers in this scenario. If you use .Wait
or .WaitAsync
you have the parallelism issues covered. Acquisition happens in parallel to your code anyways in . This is what the ring buffer is for.
So I would start all camera streams and then wait for them in one go to do the processing (assuming we have a Stream
collection:
var imageTasks = streams.Select(stream => stream.WaitAsync());
await Task.WhenAll(imageTasks);
var images = imageTasks.Select(task => task.Result)
.ToArray();
// do your processing
Although I would recommend to use .WaitFor
/.WaitForAsync
in production environments.
This code uses cooperative multitasking to wait for all the images. If you do processing you should also do it outside the UI thread via await Task.Run(...);
.
I hope that helps. If not I need more details about your current app.
Hi @parsd
I very much appreciate your answer.
I do apologies for not providing more details. The cameras are triggered by the same signal sent from PLC through their I/O ports. I am waiting for the photos by listening on PoE port on the separate thread / async. Idea is that this is 1 big photo that needs to be analyzed as such. The trigger occurs no more often than every half a second.
I have already developed this as prototype in Python and it worked great using Threading library. Since the camera stores only 1 frame after getting the trigger signal from PLC I have been able to just grab all the photos from all cameras on 1 thread and returned them to the main thread, updated gui and pushed them through ML algorithm. Now we are shifting towards .Net.
I have not yet considered the transfer errors because we were successfully able to grab photos in 0.5 sec interval though python api but maybe it is something that will become an issue.
I have already tried similar code that you have mentioned and the issue I have encountered was that the UI acted strangely and not every photo was updated every trigger or there was a delay. I have placed the code (just using for loop instead of Linq) that you have mentioned where “//processing” comment is :
private async void grabCheckBox_Checked(object sender, RoutedEventArgs e) { Device.Stream.Start(); openButton.IsEnabled = false; try { while (grabCheckBox.IsChecked ?? false) { // processing } } catch (OperationCanceledException) { // acquisition was aborted } finally { openButton.IsEnabled = true; } }
Now this might have something to do with me using the examples UI code ( i have been using the example from Getting started section " Display a Stream (WPF)").
If you advice against background worker thread I will retry the code you have mentioned and see how it goes.
Thanks again! I will try it later today and see how it goes.
UPDATE:
Ok it seems like my issue is more UI not updating all the photos on acquisition rather than the acquisition.
I will use the acync version and try fixing the UI problem. Thanks again for help.
You are welcome. Thank you for your feedback!
Did you put the Device.DeviceImage
s in our Stemmer.Cvb.Wpf
Display
? If yes these should update immediatly when the image is collected by the .Wait
method. If you want to have more control you should set the returned Image
s from the .Wait
function directly one after the other to the displays (in the UI thread). Then it appears as if they really come at the same time point.