【问题标题】:Task for taking webcam snapshots without display拍摄不显示的网络摄像头快照的任务
【发布时间】:2019-02-26 15:32:07
【问题描述】:

我想使用 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,必须以“无头”样式拍摄快照。

所以当我想使用_wcc-object 时,麻烦就开始了。我已经尝试为相应的线程调用_wcc.Dispatcher,但没有成功。

如何在独立于其余代码的自己的任务/线程中调用上面的代码?

【问题讨论】:

  • 从错误中可以清楚地看出,让多个线程与其对象交互并不快乐。可能它只需要您确保一个线程创建、交互和销毁每个对象。它可能需要一个线程来与它的任何 个对象进行交互。它甚至可能期望在 COM“STA”上下文中运行(单线程,消息泵在空闲时运行)。

标签: c# directshow


【解决方案1】:

您立即遇到的问题与线程相关,但最终它是用于网络摄像头捕获的库的不幸选择。您不需要显示相机帧,但该库正在通过将视频流渲染到 Direct3D 设备(即使它是“不可见的”),并根据请求复制最后一个已知帧来实现拍摄静止图像。

也许您应该更喜欢 DirectShow.NET 包中的 DxSnap 示例应用程序。即使也不理想:

  • 它使用 Sample Grabber 提取帧数据,无需显示过滤器
  • 它展示了如何准确地在线程之间传递数据,see here
  • 您可以避免使用多层外部控制库过于复杂

另见:

【讨论】:

    【解决方案2】:

    如果您没有 UI,那么您可能不需要将代码包装在 Task.Run 中,除非您尝试在它运行时同时执行某些操作 - 并且由于您没有使用 await 它没有't /look/ 就是这样。

    如果您想将它保存在 Task.Run 中,那么您可以在表单上使用 Invoke 方法,这将允许您在正确的线程中访问相机控件,但是我不明白它是如何实现的将解决异步运行它的问题。

    如果您没有将控件用作实际的 UI 元素,我不明白为什么您不能在单独的线程上创建它并在该线程上使用它,尽管听起来不像它的意图可以使用。

    【讨论】:

      猜你喜欢
      • 2017-12-25
      • 1970-01-01
      • 2010-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多