简体   繁体   English

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

[英]C# Raise events on another thread

I have MainForm class and some Engine class for camera control. 我有MainForm类和一些用于相机控制的Engine类。 In Engine class, I have some Camera object, which is part of SDK from camera producer. Engine类中,我有一些Camera对象,它是Camera producer的SDK的一部分。 This Camera has available OnNewFrame event, so I'll initialize: Camera具有可用的OnNewFrame事件,因此我将初始化:

camera.OnNewFrame += frameAcquired;

frameAcquired is also member of Engine class. 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) */
 }

The Engine object is a member of MainForm class. Engine对象是MainForm类的成员。 Here I am displaying images from camera and doing some other graphics stuff. 在这里,我将显示来自相机的图像并进行其他一些图形处理。 The problem is that MainForm thread sometimes hangs for a very short time. 问题在于MainForm线程有时会挂起很短的时间。 It's not so critical for displaying, but it is for camera.OnNewFrame event (I'm working with 60 fps), as this is also delayed because of main thread delay. 它对于显示不是很关键,但对于camera.OnNewFrame事件(我正在以60 fps进行操作)进行,因为这也由于主线程延迟而被延迟。

Is it possible to ensure some way, that Engine object (or Camera object in Engine ) will raise event's from it's own thread, not from main thread? 是否有可能确保一些方式,即Engine对象(或Camera中的对象Engine )将提高事件的从它自己的线程,而不是从主线程? Other words, ensure that this event raises in rate which SDK producer has set, not dependent on my main thread. 换句话说,确保此事件提高了SDK生产者设置的速率,而不依赖于我的主线程。

I have ran into a similar problem not too long ago. 不久前,我遇到了类似的问题。 I have dealt with it in C++/CLI so the same approach should also work in C# too. 我已经在C ++ / CLI中进行了处理,因此相同的方法也应该在C#中也可以使用。

I believe you have the Engine class initialized in your MainForm. 我相信您已经在MainForm中初始化了Engine类。 If you want to raise events from another thread then this object has to be initialized in another thread. 如果要从另一个线程引发事件,则必须在另一个线程中初始化此对象。

I believe you should try creating a new Thread in your MainForm constructor: 我相信您应该尝试在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);
}

This way you can keep a field for cameraThread in your MyForm class. 这样,您可以在MyForm类中为cameraThread保留一个字段。 Still, you need to write a function for the new thread to run. 尽管如此,您仍然需要编写一个函数来运行新线程。 We know it will initialize your Engine class but that is not all. 我们知道它将初始化您的Engine类,但这还不是全部。 Just to make sure the thread doesn't finish the function you gave it to run, add some check at the bottom of thread function like this: 为了确保线程没有完成您赋予它的运行功能,请在线程功能的底部添加一些检查,如下所示:

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 should join back to your main code in MainForm destructor. cameraThread应该重新加入MainForm析构函数中的主代码。

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

You can put the line this.isShown=false to your OnFormClosed() event if you wish. 您可以根据需要将this.isShown = false行添加到OnFormClosed()事件中。

If you have come this far, great. 如果您走了这么远,那太好了。 However you are not done yet, unfortunately. 但是,很遗憾,您尚未完成。 As you are now working on multiple threads you have to make sure you access objects in a thread safe manner. 在处理多个线程时,必须确保以线程安全的方式访问对象。 Long story short, check this answer . 长话短说,检查此答案

Edit: some corrections 编辑:一些更正

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM