【发布时间】:2015-07-28 21:15:46
【问题描述】:
我正在使用 BackgroundWorker 从相机中提取视频并将其写入 WinForms 表单上的 PictureBox。在 BW 线程中,我只是从相机中拉出一帧,将其放入 PictureBox,休眠,然后继续:
while (CaptureThreadRunning)
{
Thread.Sleep(5);
Image tmp = Camera.GetFrame(500);
pbCameraFeed.Image = tmp;
//this.BeginInvoke(new MethodInvoker(delegate { pbCameraFeed.Image = Camera.GetFrame(500); }));
}
问题是最终在我的屏幕上调整或移动表单会引发异常System.InvalidOperationException,并在pbCameraFeed.Image = tmp;行上显示消息Additional information: Object is currently in use elsewhere.
我假设库试图在我的 while 循环同时绘制与 PictureBox 相关的内容,所以我切换到上面注释掉的 this.BeginInvoke 实现。不幸的是,这大大降低了我的帧率。我在一台速度非常慢的 Mini PC 上运行此代码,这可能会导致该问题。
我真正想要的是一种可靠地更新我的图形用户界面的方法,它不会使我的帧率下降近一半。还有其他标准方法可以做到这一点吗? BW 线程似乎非常适合此应用程序,但我是否遗漏了什么?
谢谢
【问题讨论】:
-
如果你用
try {} catch {}捕获这个异常怎么办? -
您是否尝试保留
BeginInvoke但增加您的Sleep时间? 5 毫秒低于Thread.Sleep的精度(大约为 15 毫秒,具体取决于您的操作系统上的活动),因此您绝对可以增加它。这应该有助于减少负载/延迟。 -
增加睡眠时间会减少延迟?我假设在 PictureBox 更新之间增加更多时间会进一步降低帧速率(即使它是很小的数量)。我会尝试调整睡眠时间,看看有什么效果。
-
@Fabjan 不是一个好的建议。例外是有原因的。它说你做错了什么,应该修复而不是隐藏在 try/catch 后面。
-
@user912447 相反,你现在每 5 毫秒告诉 UI 线程“嘿,停止你正在做的事情并为我更新那个图片框”。如果您在更新上放轻松一点,UI 将有更多时间来做更多的事情,比如重绘自身和响应用户的交互。这也是为什么您将长时间运行的操作放在 BW 上的原因;所以 UI 可以做其他事情并保持响应。因此,如果您将睡眠时间设置为 33 毫秒左右,您应该会获得相当于 30 FPS 的效果。
标签: c# multithreading winforms webcam