从辅助线程更新控制:调用性能是否至关重要?

Giu*_*ini 4 c# controls multithreading invoke begininvoke

我正在开发的一个c#应用程序主要包括对来自摄像头的图像执行操作并将其打印在图片框上.它有一个用c ++编写的库,它从网络摄像头(imgcam)中检索图像,然后复制它们(imgcam_copy),然后将它们传送给请求它们的托管代码.反过来,应用程序的托管部分由一个辅助线程组成,该辅助线程执行一个while循环,该循环从非托管库中获取图像并将它们打印到图片框.

一切正常,一切都是最精致的部分,即从非托管代码到托管代码的动态资源管理对我来说似乎很清楚,我知道我正在做什么(至少我希望如此),但问题在于编写使线程正常工作所需的代码.事实上,即使在浏览网页数小时之后,我仍有很多事情不清楚.

我不得不用UI线程打印图像,所以我必须依赖Invoke.

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

我有很多问题:

1)调用昂贵的操作?我已经做了很多努力来减少主要操作在图像上的执行时间,在显示结果时浪费部分收益会令人失望.

2)您是否认为同步使用Invoke或异步BeginInvoke +图像副本更好?

3)将Image作为函数参数但是作为类的成员访问它是否有帮助?

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

4)也许你不会分享我对性能的担心,但我想知道你是否分享了线程安全性.UI线程只是想在非UI线程复制它时显示图像,依赖异步机制真的不安全吗?

Jim*_*hel 6

调用Invoke很昂贵,因为它涉及线程上下文切换并且(可能)等待UI线程变得可用.但是,如果您的UI线程没有被捆绑在一起做其他一些事情,并且您不想尝试每秒进行数百个图片盒更新,那么它不太可能是一个明显的问题.如果图像具有任何显着的大小,绘制像素将花费很多时间,以至于它所需的微秒Invoke将是无关紧要的.

更重要的是,您必须在UI线程上进行更新.因此,您要么在UI线程上执行所有处理,要么Invoke用于编组UI线程的更新.由于您不希望绑定UI线程进行计算,因此您实际上没有选择权.

拥有img作为函数参数或作为类的成员之间的区别是微不足道的.

BeginInvoke可能很有用,但你必须要小心.所有这些BeginInvoke都是对请求进行排队,以便您的后台线程可以继续其工作,并且UI线程可以在有时间时更新其显示.排队这么多请求是非常容易的BeginInvoke,因为UI线程花费了大部分时间来处理这些请求,并且UI的其余部分似乎被锁定,因为在更新操作之后用户启动的操作被塞进队列中.如果您每秒进行许多图像更新,当然取决于图像大小,您的UI线程将永远不会赶上.您的UI将锁定,最终您将耗尽内存以排队请求.

您的主要性能瓶颈似乎是在图像上进行计算,然后显示图像.这两项操作都是如此耗费时间,无论您花费多少时间Invoke都可能无关紧要.

如果您的程序使用性能Invoke足够好,那么您可能最好不要使用它.您可以尝试使用,BeginInvoke但正如您所说,需要克隆图像.此外,您可能会遇到锁定的UI.

简而言之,您的问题的答案是,"这取决于".我不太了解您的图像处理或执行该处理所需的时间.如果你很好奇,试试看吧BeginInvoke.可能发生的最糟糕的是你的程序崩溃,你必须回去使用Invoke.但一定要经过长时间的彻底测试.

你的上一个问题不清楚.如果你问在后台线程上进行UI更新是否有危险,那么答案就是响亮的"是的!" 在UI线程以外的任何线程上更新UI可能导致各种奇怪和奇妙的错误,这些错误几乎不可能有时复制,并且很难追踪.Windows期望在单个线程上更新UI元素.