Question

A c# application I’m developing consists essentially of performing operations on images coming from a camera and printing them on a picturebox. It has a library written in c++ that retrieves images from a webcam (imgcam), and makes copies of them (imgcam_copy), then they are delivered to the managed code who is requesting them. In turn the managed part of the application consists of a secondary thread who executes a while cycle that takes images from the unmanaged library and prints them to a picturebox.

Everything works fine and the most delicate part of everything, that is the management of dynamic resources from unmanaged to managed code seems clear to me and I’m aware of what I’m doing (at least I hope), but the problem is with the writing of the code necessary for making threads work properly. Indeed there are many things that are not clear to me, even after browsing the web for hours.

I’m compelled to print the image with UI thread, so I have to rely on Invoke.

    delegate void setImageCallback(Image img);
    private void showFrame(Image img)
    {
        if (pboxCam.InvokeRequired)
        {
            this.Invoke(new setImageCallback(showFrame), img);
        }
        else
        {
            pboxCam.Image = img;
        }
    }

I have many questions:

1) Is Invoke a costly operation? I’ve made many efforts to reduce the execution time of main operations on images, it would be disappointing to waste part of the gain in just showing the result.

2) Do you think that it is better to use synchronously Invoke or asynchronously BeginInvoke+copy of image?

3) Could it be helpful not having Image as function parameters but accessing it as member of a class ?

    private delegate void setImageCallback();
    private void showFrame()
    {
        if (pboxCam.InvokeRequired)
        {
            this.Invoke(new setImageCallback(showFrame));
        }
        else
        {
            pboxCam.Image = cm.bitmap;
        }
    }

4) maybe you won’t share my worry for the performance, but I would like to know if you share the one for thread safety. The UI thread just wants to display an image while the non-UI thread makes a copy of it, is it really unsafe to rely on an asynchronous mechanism?

Was it helpful?

Solution

Calling Invoke is expensive only in that it involves a thread context switch and (possibly) waiting for the UI thread to become available. But if your UI thread isn't tied up doing a bunch of other stuff, and you're not trying to do hundreds of picturebox updates a second, then it's unlikely to be a noticeable problem. If the image is of any significant size, drawing the pixels is going to take so much time that the microseconds it takes for the Invoke will be insignificant.

More importantly, you must do the update on the UI thread. So either you do all of your processing on the UI thread, or you use Invoke to marshal the update to the UI thread. Since you don't want to tie up the UI thread doing calculations, you don't really have a choice.

The difference between having img as a function parameter or as a member of a class is insignificant.

BeginInvoke can be useful, but you have to be careful. All BeginInvoke does is queue a request so that your background thread can get on with its work and the UI thread can update its display when it has time. It's very easy to queue so many requests with BeginInvoke that the UI thread is spending near all of its time handling those requests and the rest of the UI appears to lock up because user-initiated actions got stuffed in the queue after the update actions. If you're doing many dozens of image updates per second, depending of course on the image size, your UI thread will never catch up. Your UI will lock up and eventually you'll run out of memory to queue requests.

It appears that your major performance bottlenecks here are doing the calculations on the image and then displaying the image. Both of those operations are so time intensive that whatever time you spend in Invoke is likely irrelevant.

If your program's performance using Invoke is good enough, then you're probably better off leaving it as it is. You can try using BeginInvoke but as you say that'll require cloning the image. In addition, you might experience a locked-up UI.

In short, the answer to your questions is, "it depends." I don't know enough about your image processing or the amount of time it takes to do that processing. If you're curious, try it with BeginInvoke and see. Worst that can happen is that your program crashes and you have to go back to using Invoke. But be sure to test thoroughly over an extended period.

Your last question is unclear. If you're asking if it's dangerous to do UI updates on a background thread, the answer is a resounding "Yes!" Updating the UI on any thread other than the UI thread can lead to all manner of strange and wonderful bugs that are nearly impossible to duplicate at times, and very difficult to track down. Windows expects UI elements to be updated on a single thread.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top