我有一个Camera类,它在高FPS下产生非常大的图像,需要由ImageProcessor类处理。我还有一个显示此信息的WPF控件,我的视图。我需要每个组件都需要在它自己的线程上运行,因此它不会锁定处理。
方法1)Camera具有ImageProcessor所订阅的Action<Image> ImageCreated
。 ImageProcessor有一个Action<Image, Foo> ImageCreated
,其中包含一个更改的Image和Foo结果,供View显示。
方法2)Camera具有线程安全(使用锁和监视器)ProducerConsumer,它生成Images,ImageProcessor等待和使用。观点也是如此。
方法2很好,因为我可以创建和管理自己的线程。
方法1很好,因为我有多个ImageProcessors订阅了Camera类。但我不确定谁的线程正在做重量级工作,或者Action是否浪费时间创建线程。这些图像每秒都会出现很多次。
我正在尝试尽快将图像放到我的View中,而不会造成处理或导致View锁定。
思想?
答案 0 :(得分:3)
除非您自己使用,否则使用方法1)不会引入任何多线程。调用一个动作(除非你调用BeginInvoke
)同步执行,就像任何正常的方法调用一样。
我会提倡方法2)。没有必要将它绑定到一个单一的消费者。如果您将此队列用作X摄像机和Y处理器之间的单点联系,则可以将摄像机与处理器分离,并可以单独修改X和Y的值。
修改强>
冒着在这里被指控博客垃圾邮件的风险,我记得我写了一个类似的(如果不是完全匹配)的组件,用于你之前寻找的东西。看看这是否有帮助:
它的要点是,您为队列提供了一个委托,该委托可以处理单个项目 - 在您的情况下,Image
- 在构造函数中,然后调用Start
。当项目使用Enqueue
添加到队列时,它们会自动分派到适当的线程并进行处理。
例如,如果你想让图像移动Camera-&gt; Processor-&gt; Writer(并且每个都有一个可变数),那么我会做这样的事情:
ProcessQueue<Foo> processorQueue = new ProcessQueue<Foo>(f => WriteFoo(f));
ProcessQueue<Image> cameraQueue = new ProcessQueue<Image>(i => processorQueue.Enqueue(ProcessImage(i)));
您可以使用cameraQueue
改变processorQueue
(控制图像处理)和SetThreadCount
(控制写入磁盘)中的线程数。
完成后,只要相机拍摄图像,您就可以拨打cameraQueue.Enqueue(image)
。
答案 1 :(得分:1)
方法一不起作用 - Action<T>
将在调用它的线程上执行。虽然你应该在这样的场景中使用事件而不是普通代理。
方法二是可行的方法,但是如果可能的话,你应该使用.NET 4.0的新thread-safe collection而不是自己进行同步 - 我们都知道即使是最简单的多线程也是多么困难代码正确。