在没有显示的情况下拍摄网络摄像头快照的任务
Task for taking webcam snapshots without display
我想使用 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();
我最难处理的对象是存储在cam1._wcc
中的webCameraControl
:这个对象继承自System.Windows.Controls.UserControl
,可以附加到UI。但就我而言,我没有任何 UI,必须以 "headless" 样式拍摄快照。
因此,当我想使用 _wcc
-对象时,麻烦就开始了。我已经尝试为相应的线程调用 _wcc.Dispatcher
但没有成功。
如何独立于其他代码独立于 task/thread 调用上面的代码?
如果您没有 UI,那么您可能不需要将代码包装在 Task.Run
中,除非您尝试在 运行 中同时执行某些操作] - 因为你没有使用 await 它/看起来/不像是这种情况。
如果您想将其保留在 Task.Run 中,那么您可以在表单上使用 Invoke
方法,这将允许您在正确的线程中访问相机控件,但是我看不出它如何异步解决 运行 的问题。
如果您没有将控件用作实际的 UI 元素,我不明白为什么您不能在单独的线程上创建它并在该线程上使用它,尽管它不会听起来这就是它的用途。
您立即遇到的问题与线程相关,但最终它是用于网络摄像头捕获的库的不幸选择。您不需要显示相机帧,但该库正在通过将视频流渲染到 Direct3D 设备(即使它是 "invisible" 也是一种演示)并根据请求复制最后一个已知帧来实现拍摄静止图像。
也许您更喜欢 DirectShow.NET 包中的 DxSnap
示例应用程序。虽然也不理想:
- 它使用 Sample Grabber 提取帧数据而不需要显示过滤器
- 展示了如何在线程间准确传递数据,see here
- 你避免了多层外部控制库的过度复杂化
另请参阅:
- Efficiently grabbing pixels from video
- Calling a function in another thread C#
我想使用 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();
我最难处理的对象是存储在cam1._wcc
中的webCameraControl
:这个对象继承自System.Windows.Controls.UserControl
,可以附加到UI。但就我而言,我没有任何 UI,必须以 "headless" 样式拍摄快照。
因此,当我想使用 _wcc
-对象时,麻烦就开始了。我已经尝试为相应的线程调用 _wcc.Dispatcher
但没有成功。
如何独立于其他代码独立于 task/thread 调用上面的代码?
如果您没有 UI,那么您可能不需要将代码包装在 Task.Run
中,除非您尝试在 运行 中同时执行某些操作] - 因为你没有使用 await 它/看起来/不像是这种情况。
如果您想将其保留在 Task.Run 中,那么您可以在表单上使用 Invoke
方法,这将允许您在正确的线程中访问相机控件,但是我看不出它如何异步解决 运行 的问题。
如果您没有将控件用作实际的 UI 元素,我不明白为什么您不能在单独的线程上创建它并在该线程上使用它,尽管它不会听起来这就是它的用途。
您立即遇到的问题与线程相关,但最终它是用于网络摄像头捕获的库的不幸选择。您不需要显示相机帧,但该库正在通过将视频流渲染到 Direct3D 设备(即使它是 "invisible" 也是一种演示)并根据请求复制最后一个已知帧来实现拍摄静止图像。
也许您更喜欢 DirectShow.NET 包中的 DxSnap
示例应用程序。虽然也不理想:
- 它使用 Sample Grabber 提取帧数据而不需要显示过滤器
- 展示了如何在线程间准确传递数据,see here
- 你避免了多层外部控制库的过度复杂化
另请参阅:
- Efficiently grabbing pixels from video
- Calling a function in another thread C#