C# 在另一个线程上引发事件

C# Raise events on another thread

我有 MainForm class 和一些 Engine class 用于相机控制。在 Engine class 中,我有一些 Camera 对象,它是来自相机生产商的 SDK 的一部分。 此 Camera 有可用的 OnNewFrame 事件,所以我将初始化:

camera.OnNewFrame += frameAcquired;

frameAcquired 也是引擎 class.

的成员
 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 class 的成员。在这里,我正在显示来自相机的图像并做一些其他图形工作。问题是 MainForm 线程有时会挂起很短的时间。它对于显示不是那么重要,但它对于 camera.OnNewFrame 事件(我正在使用 60 fps),因为这也因为主线程延迟而延迟。

是否有可能以某种方式确保 Engine 对象(或 Engine 中的 Camera 对象)将从它自己的线程而不是主线程引发事件?换句话说,确保这个事件以SDK生产者设置的速率提升,而不依赖于我的主线程。

不久前我 运行 遇到过类似的问题。我已经在 C++/CLI 中处理过它,所以同样的方法也应该适用于 C#。

我相信您已经在 MainForm 中初始化了引擎 class。如果您想从另一个线程引发事件,则必须在另一个线程中初始化此对象。

我相信您应该尝试在 MainForm 构造函数中创建一个新的 Thread

MyForm()
{
    //rest of your constructor
    cameraThread = new Thread(new ParameterizedThreadStart(CameraRun));
    cameraThread.Name = "Camera Thread";
    cameraThread.Start(this);
    while (!cameraThread.IsAlive)
        Thread::Sleep(1);
}

这样您就可以在 MyForm class 中为 cameraThread 保留一个字段。不过,你需要为新线程编写一个函数到运行。我们知道它将初始化您的引擎 class 但这还不是全部。只是为了确保线程没有完成你给它的函数 运行,在线程函数的底部添加一些检查,如下所示:

void CameraRun(Object myForm)
{
    //you can use (myForm as MyForm)
    //and make calls from here
    /*
    Engine initialization etc
    */
    while((myForm as MyForm).isShown)
        Sleep(100);
}

cameraThread 应该连接回 MainForm 析构函数中的主代码。

~MyForm()
{
    //rest of your destructor
    this.isShown=false;
    cameraThread.Join();
}

如果您愿意,可以将行 this.isShown=false 添加到 OnFormClosed() 事件中。

如果你已经走到这一步,那就太好了。然而,不幸的是,你还没有完成。由于您现在正在处理多个线程,因此您必须确保以线程安全的方式访问对象。长话短说,检查这个 answer.

编辑:一些更正