【发布时间】:2015-04-24 18:40:34
【问题描述】:
我有MainForm 类和一些Engine 类用于相机控制。在Engine 类中,我有一些Camera 对象,它是来自相机生产商的SDK 的一部分。
这个Camera 有可用的OnNewFrame 事件,所以我将初始化:
camera.OnNewFrame += frameAcquired;
frameAcquired 也是 Engine 类的成员。
private void frameAcquired(object sender, EventArgs e)
{
/* this event should periodically raise after ~17ms,
but sometimes it hangs for a short time
(when I overloads main thread) */
}
Engine 对象是MainForm 类的成员。在这里,我正在显示来自相机的图像并做一些其他的图形工作。问题是MainForm 线程有时会挂起很短的时间。它对于显示不是那么重要,但它对于 camera.OnNewFrame 事件(我正在使用 60 fps),因为这也由于主线程延迟而延迟。
是否有可能以某种方式确保Engine 对象(或Engine 中的Camera 对象)会从它自己的线程而不是主线程引发事件?换句话说,确保此事件以 SDK 生产者设置的速率提高,而不依赖于我的主线程。
【问题讨论】:
-
很不清楚为什么会出现这个问题,如果这导致相机固件因某种原因爆炸,您将不得不复制图像。最终有一个基本的firehose问题,当相机吐出图像的速度超过UI线程可以显示它们的速度时,如果你不使用任何类型的视频加速,你肯定会以60 fps的速度突破极限,那么你会输不定期更新。
-
显示没问题。我正在使用一些框架队列,如果旧框架尚未显示,我将丢弃新框架的显示。但我需要将它们全部保存(在另一个线程上执行此操作没有问题)。但有时当主线程挂起时(例如调整表单大小 -> 我的代码中的一些计算,以及其他情况),事件引发也会挂起。
-
“事件引发”只有在您错误地使用 Invoke() 而不是 BeginInvoke() 时才会挂起。
-
您可以使用
BeginInvoke代替Invoke(wpf 中的InvokeAsync),这不会阻止您的事件处理。或者您可以在单独的线程中执行事件处理程序(因此,如果一个被阻塞,其他人仍在处理),这必须包括同步。但当然正确的方法是实现某种消费者-生产者队列,屏幕占据最后一帧。 -
我没有在这里使用
Invoke也不是BeginInvoke。我创建Engine对象,并在Engine类中初始化事件。你能建议我如何使用BeginInvoke吗?不幸的是,我不知道该事件是如何在 SDK 内部引发的。
标签: c# multithreading events main