Click here to Skip to main content
11,935,467 members (63,674 online)
Click here to Skip to main content
Add your own
alternative version


11 bookmarked

Preventing Unexpected Message Pumping in Third Party Libraries - An example using DirectShow

, 7 Jun 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
This article shows a tidy solution to unexpected third party code pumping messages.


This project demonstrates a problem inherent in the design of windowing applications and a simple solution to the problem. The problem is that when you call a third party library, there is no guarantee that the library will not call Application.DoEvents() or in some other way cause pumping of your application's message queue. This is normally not a problem, but it can set up a race condition in your code.

For example, assume the user has rapidly clicked a button several times in succession. Your code is busy processing the first button click and your application is in an inconsistent state. You probably assumed (justifiably) that throughout your button event handler, you were quite safe from being preempted by another button click. You are after all using a single threaded model with an event queue that serialises user input. In the button click event handler, you then make a call out to some third party code. That third party code, for whatever reason, calls Application.DoEvents() or pumps messages in native code. Suddenly, the next button click event is fired, and very quickly throws an exception due to the inconsistent state left by the partly run event handler of the first click.


I ran into this problem while working on a C# WinForms application that uses DirectShow to do video recording. The problem was found by a tester who rapidly clicked on various control buttons and caused a null ref exception. The diagnosis of the problem is recorded in a UseNet thread here.

I considered other solutions to the problem such as dropping all user input and timer messages during the processing of a user input or timer message. This solution would prevent the reentrancy, but dropping messages could cause other problems.


To prevent the nesting of event handlers, we need to prevent the message loop in the third party code - the DirectShow code in this case - from dequeing and processing messages destined for windows in your application. The solution I used to do this was to start a second thread with its own message loop. This code fragment is from the Main() method of the application:

SynchronizationContext context = null;
bool started = false;

ThreadStart startRoutine =
        // Set the sync context on the thread
        context = new WindowsFormsSynchronizationContext(); 

        // Run a dedicated message loop with no forms

// Start up the DS runner
Thread runner = new Thread(startRoutine);

Note that a synchronization context is created and set on the new thread. This is to allow easy inter-thread messaging using SynchronizationContext.Send(). Simply place the calls to the third party library (the one that pumps messages) in a SendOrPostCallback delegate and Send() it to the other thread.

SendOrPostCallback a =
        //Call code that pumps messages here

context.Send(a, null);

One detail is that a WindowsFormsSynchronizationContext is used, not a plain SynchronizationContext. The problem is that SynchronizationContext.Send() actually executes the SendOrPostCallback on the calling thread! The WindowsFormsSynchronizationContext.Send() executes it correctly on the target thread.

Running the Demo

The demo application has two buttons. The first button runs a DirectShow call on the main thread after first queuing a message on the main thread's message queue. When the DirectShow call is made, the queued message is processed, nested inside the button click.

The second button runs the DirectShow call synchronously on a dedicated thread. This means that the queued message is not processed until after the button click handler returns.

Points of Interest

It should be noted that the solution to the problem demonstrated here is not production ready. If you use it, you will want to package it up in a helper class somehow. You'll also need to consider what happens to any exceptions thrown in the second thread (hint: if you use Send(), they will come back to the main thread; if you use Post(), they'll need to be handled on the second thread).


I do not consider myself an expert in either DirectShow or in the details of Windows programming, be it Win32 or .NET. This article is submitted in the hope that it will help other people avoid the same situation, but also in the hope that more expert programmers will suggest other solutions.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Felix Collins
New Zealand New Zealand
No Biography provided

You may also be interested in...

Comments and Discussions

GeneralThanks for sharing your solution Pin
Christian Rodemeyer8-Jun-09 22:03
memberChristian Rodemeyer8-Jun-09 22:03 
GeneralRe: Thanks for sharing your solution Pin
Felix Collins10-Jun-09 12:28
memberFelix Collins10-Jun-09 12:28 
GeneralRe: Thanks for sharing your solution Pin
Oneibus22-Dec-10 10:08
memberOneibus22-Dec-10 10:08 
GeneralDescribe solution Pin
zlezj1-Jun-09 22:08
memberzlezj1-Jun-09 22:08 
GeneralRe: Describe solution Pin
Ant21002-Jun-09 2:30
memberAnt21002-Jun-09 2:30 
GeneralRe: Describe solution Pin
Felix Collins3-Jun-09 12:28
memberFelix Collins3-Jun-09 12:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.151126.1 | Last Updated 7 Jun 2009
Article Copyright 2009 by Felix Collins
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid