This project has moved and is read-only. For the latest updates, please go here.

Multithreading WinForms issue

Jan 11, 2013 at 8:32 AM

Hi,

Your library (MjpegProcessor.dll - WinForms) works great when called from UI (main thread). When it's called from another thread, FrameReady event never fires.

Test case:

 

        WorkerThread = new Thread(WorkerThreadFunction);
        WorkerThread.Start();         

        void WorkerThreadFunction() {
            try {
                MjpegDecoder mjpeg = new MjpegDecoder();
                mjpeg.FrameReady += new EventHandler<FrameReadyEventArgs>(mjpeg_FrameReady);
                mjpeg.ParseStream(new Uri("http://...."));
            }
            catch {
            }
        } 

        void mjpeg_FrameReady(object sender, FrameReadyEventArgs e) {
        ...
        }

 

FrameReady event fires properly when "WorkerThreadFunction()" is called from the main thread.

Any ides why this happens ?

Regards,
Benjamin

Jan 11, 2013 at 4:02 PM

Try instantiating the MjpegDecoder object on the main thread...that may allow it to work in this scenario.

Jan 13, 2013 at 9:59 PM

Hi peekb!

Thanks for your reply.
My goal was to put a few MjpegDecoder instances it in worker threads for better UI response from the main thread.

Still don't understand why it doesn't fire "FrameReady" event from another thread ?

Regards, Benjamin

Jan 14, 2013 at 7:23 PM

The issue is that the current code expects a SynchronizationContext.  When created inside of a WorkerThread, there isn't one.  The fix is to either create the object outside the WorkerThread, or edit the source code and remove the calls to _context.Post() (or "if" them out when null) and call the contents of the Post immediately, which will require you to handle your own thread marshaling in cases where it's necessary.

The next version of the library will try to improve this...

Jan 15, 2013 at 8:41 AM

Got it! Replaced

		_context.Post(delegate {
                        // create a simple GDI+ happy Bitmap
                        Bitmap = new Bitmap(new MemoryStream(frame));

                        // tell whoever's listening that we have a frame to draw
                        if (FrameReady != null)
                            FrameReady(this, new FrameReadyEventArgs { FrameBuffer = CurrentFrame, Bitmap = Bitmap });
                    }, null);

with

                if (_context != null) {
                    _context.Post(delegate {
                        // create a simple GDI+ happy Bitmap
                        Bitmap = new Bitmap(new MemoryStream(frame));

                        // tell whoever's listening that we have a frame to draw
                        if (FrameReady != null)
                            FrameReady(this, new FrameReadyEventArgs { FrameBuffer = CurrentFrame, Bitmap = Bitmap });
                    }, null);
                }
                else {
                    Bitmap = new Bitmap(new MemoryStream(frame));

                    // tell whoever's listening that we have a frame to draw
                    if (FrameReady != null)
                        FrameReady(this, new FrameReadyEventArgs { FrameBuffer = CurrentFrame, Bitmap = Bitmap });
                }

and it works!

Thank you! Great library :-)

Jan 15, 2013 at 7:50 PM

That's it exactly.  I'll look to add this to the next release.  Thanks!