1

这就是问题所在:我有一个自定义硬件设备,我必须在 C#/WPF 中从中获取图像并将它们显示在一个窗口中,所有这些都具有 120+ FPS。

问题是没有事件表明图像已准备就绪,但我必须不断轮询设备并检查是否有任何新图像然后下载它们。

显然有几种方法可以做到这一点,但我还没有找到合适的方法。

这是我尝试过的:

  • 一个简单的计时器(或 DispatcherTimer) - 适用于较慢的帧速率,但我无法让它超过 60 FPS。

  • 一个单线程无限循环 - 非常快,但我必须将 DoEvents/它的 WPF 等效项放入循环中,以便重绘窗口;这会产生一些其他不需要的(奇怪)后果,例如某些控件未触发的按键事件等。

  • 在另一个线程中进行轮询/下载并在 UI 线程中显示,如下所示:

     new Thread(() =>
            {
                while (StillCapturing)
                {
                    if (Camera.CheckForAndDownloadImage(CameraInstance))
                    {
                        this.Dispatcher.Invoke((Action)this.DisplayImage);
                    }
                }
            }).Start();
    

    好吧,这工作得比较好,但是会给 CPU 带来相当大的负载,如果它没有超过一个 CPU/核心,当然会完全杀死机器,这是不可接受的。另外,我这种方式存在大量线程争用。

问题很明显——有没有更好的选择,或者在这种情况下是其中一种方法吗?

更新:
我不知何故忘了提到这一点(好吧,写这个问题时忘了考虑它),但是我当然不需要显示所有帧,但是我仍然需要捕获所有帧以便保存它们到硬盘。

Update2: 我发现 DispatcherTimer 方法很不是因为它不能足够快地处理所有事情,而是因为 DispatcherTimer 在触发滴答事件之前等待下一次垂直同步;这在我的情况下实际上很好,因为在滴答事件中,我可以将所有待处理的图像保存到内存缓冲区(用于将图像保存到磁盘)并只显示最后一个。

至于被捕获完全“杀死”的旧计算机,WPF似乎退回到非常慢的软件渲染。我可能无能为力。

感谢所有的答案。

4

2 回答 2

1

我认为您正在尝试一种过于简单化的方法。这就是我要做的。

a) 在您的轮询循环中放置一个 Thread.Sleep(5),这应该可以让您接近 120 fps,同时仍然保持较低的 CPU 时间。

b) 仅每 5 帧左右更新一次显示。这将减少处理量,因为我不确定 WPF 是否能够处理超过 60fps 的速度。

c) 使用 ThreadPool 为每个帧生成一个子任务,然后将其保存到磁盘(每帧一个单独的文件中),这样您就不会受到磁盘性能的限制。额外的帧只会堆积在内存中。

就我个人而言,我会按此顺序实施它们。机会是 a 或 b 将解决您的问题。

于 2010-10-28T13:05:34.377 回答
-1

您可以执行以下操作(所有伪代码): 1. 运行一个工作线程来处理捕获过程:

List<Image> _captures = new List<Image>();
 new Thread(() =>
    {
        while (StillCapturing)
        {
            if (Camera.CheckForAndDownloadImage(CameraInstance))
            {
                lock(_locker){_captures.Add(DisplayImage);


            }
        }
    }).Start();
  1. 让调度程序计时器线程获取最新捕获的图像(显然自上次滴答以来它会错过一些捕获)并显示。因此,UI 线程被限制并尽可能少地做,它没有做所有的“捕获”,这是由工作线程完成的。抱歉,我无法格式化这个位(但你明白了):

    void OnTimerTick(can't remember params)
    

    { 图像图像显示;锁定(_locker){imageToDisplay = _captures[k.Count - 1]; 显示功能(图像显示);}

  2. 可能是该列表是一个队列,而另一个线程用于排空队列并写入磁盘或其他任何东西。

于 2010-10-28T13:18:53.963 回答