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.
编辑:一些更正
我有 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.
编辑:一些更正