By interfere I mean, while this ActiveX control is performing a potentially long running operation the UI owning thread "magically" resumes event processing. I suspect this is intentional; the vendors users probably complained that their UIs froze whenever they performed this potentially long running operation. Since this 3rd party control was consumed mostly by single threaded VB6 apps the vendor may have decided to respond to these complaints in a way that causes a problem for Windows Forms apps.
I have lots of theories (e.g., there may be some interplay between the ActiveX control being free threaded while the main thread of the WinForms app runs in a single threaded apartment) but little time to investigate them. So I'm avoiding the problem by running the ActiveX control on a separate thread.
The managed ThreadPool is a wonderful place to run this code; I don't have to manage the setup or teardown of ThreadPool threads and the operation isn't so long running that it will prevent other threads from accessing the ThreadPool.
Since I'm running the ActiveX control in a separate thread to avoid interference with the UI thread, not because I want to execute concurrently, I need to wait until it's done before proceeding (and I *want* the UI to be unresponsive during this time - even have the WaitCursor showing). So a ManualResetEvent is signaled once the operation is complete.
What does this have to do with Pre 3.0 C#? Well, C# 2.0 introduced anonymous methods. These provide a way to succinctly pass short behavior (no more than a few operations) without having to declare a separate method.
So something along the lines of the following:
// do something here
does the trick!