Majak
Majak

Reputation: 1633

C# Raise events on another thread

I have MainForm class and some Engine class for camera control. In Engine class, I have some Camera object, which is part of SDK from camera producer. This Camera has available OnNewFrame event, so I'll initialize:

camera.OnNewFrame += frameAcquired;

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

The Engine object is a member of MainForm class. 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. 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.

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? Other words, ensure that this event raises in rate which SDK producer has set, not dependent on my main thread.

Upvotes: 0

Views: 1842

Answers (1)

Bahadir Acar
Bahadir Acar

Reputation: 66

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.

I believe you have the Engine class initialized in your MainForm. 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:

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. 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. 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.

~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.

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

Upvotes: 1

Related Questions