I have a .NET application containing a WinForm. This WinForm contains an unmanaged ActiveX control and a few other controls. This application works fine in standalone mode. Now we want to publish some kind of interface so this Winform can be used from unmanaged C++/MFC applications using Interop functionality. The client applications will Show this form in a modeless manner. When the user inputs the details the same are passed to the client using COM event source/sink (or connection point) method.
I have followed various articles and one of the method that works for us is
http://codebetter.com/blogs/peter.van.ooijen/archive/2005/06/03/64041.aspx
But if I start more than one thread from the same client application, the second instance of form throws access violation exceptions because the ActiveX control on the form expects the thread to always be a UI thread (based on my observation).
Could you tell me what is the right way to expose a WinForm functionality to unmanaged client applications via Interop?
Many thanks
The article you linked gives you all the info you need to properly host a Form in an unmanaged app. You should look for the source of the AV elsewhere. Get that started by using the debugger. You can force it to stop on the exception with the Debug + Exceptions dialog, Thrown checkbox.
The STA requirement is almost always sufficient to keep an ActiveX control operating properly in a multi-threaded application. It provides the guarantee that all method calls are made on the exact same thread in which the coclass was created. In other words, any instance variables inside the coclass implementation are guaranteed to be used in a thread-safe manner.
One guarantee you don’t have here though is whether the control properly handles global state. Instance variables are safe, global variables are not when you use the control in different threads. A possible workaround for that is to use only one thread instead of one STA thread for each form instance. That’s a bit tricky, you’ll need an invisible helper form that manages the thread. Keeping it alive and creating new form instances through its Invoke() method.
Before you go there, find out what’s crashing first.