我想用DirectShow在Windows上拍摄网络摄像头快照。这些快照将保存到磁盘,而不显示这些图像。我想启动快照进程,每隔一秒拍摄一次快照,直到我停止它为止,同时主进程继续。
所以我选择Yet Another Web Camera Control用于DirectShow与C#一起使用,并且该演示工作正常。
但是当我在自己的任务中使用包装器时遇到问题,我得到了典型的线程错误The calling thread cannot access this object because a different thread owns it.
调用代码如下所示:
Task.Run(() =>
{
using (var cam1 = new SnapshotCam(camList.First(), "person", webCameraControl))
{
// Act
Bitmap image = null;
if (!cam1._wcc.IsCapturing)
{
cam1._wcc.StartCapture(cam1._cameraId);
Task.Delay(500).Wait();
}
image = cam1._wcc.GetCurrentImage();
// Assert
Assert.NotNull(image);
}
}).Wait();
我要处理的难题是存储在webCameraControl
中的cam1._wcc
:这个对象继承自System.Windows.Controls.UserControl
,可以附加到UI。但在我的情况下,我没有任何UI,快照必须以“无头”风格。
因此,当我想使用_wcc
对象时,麻烦就开始了。我已经尝试将_wcc.Dispatcher
称为相应的线程,但没有成功。
如何在独立于其余代码的自己的任务/线程中调用上面的代码?
你立即遇到的问题是线程相关,但最终它是一个不幸的选择库摄像头捕获。您不需要显示相机框架,但是图书馆正在通过将视频流渲染到Direct3D设备(即使它是“不可见”的呈现方式)来实现静止图像,并根据请求复制最后一个已知帧。
也许您应该更喜欢DirectShow.NET包中的DxSnap
示例应用程序。即使不理想也是:
也可以看看:
如果您没有UI,那么您可能不需要将代码包装在Task.Run
中,除非您在运行时尝试同时执行某些操作 - 并且因为您没有使用等待它不会/ look /就是这样。
如果您想将它保存在Task.Run中,那么您将在表单上使用Invoke
方法,这将允许您在正确的线程中访问相机控件,但是我不知道如何解决问题异步运行它。
如果您没有将控件用作实际的UI元素,我不明白为什么你不能在一个单独的线程上创建它并在该线程上使用它,尽管听起来不像它是如何被使用的。