I recently ran into an interesting threading problem that I wanted to share, so that perhaps I can save some people from the same confusion I had.
I started with a C# application someone else had written. I’ll call it “DeltaEngine” for the purpose of this post. DeltaEngine calls into a native assembly and handles certain events from it.
I created a solution where I referenced DeltaEngine as a library project, and called into it from a VB project. I’ll call this project “VBApp”. So, the reference structure looks like this:
VBApp (VB) -> DeltaEngine (C#) -> NativeCode
When I ran my solution with VBApp as the startup project, it would wait indefinitely for an event to be caught in DeltaEngine from the Native Code. However, I noticed if I made the exact same calls with DeltaEngine as the startup project, it handled the event as expected. I spent a lot of time trying to figure this out and was completely stumped.
Eventually I talked to someone who pointed out that VB projects use Single Threaded Apartment (STA) by default, while C# projects use Multithreaded Apartment (MTA) by default. Because DeltaEngine was originally developed with a C# project as the startup application, it assumed MTA threading. Since I started calling the code from a VB startup project, I was running it with STA threading, without realizing it. Because of this, the DeltaEngine code started waiting for the event after it had already been raised, so it waited indefinitely. If I set DeltaEngine as the startup project and made the same calls, it would use MTA threading and work as expected.
The fix was to add the MTAThreadAttribute to my Sub Main in VBApp. After this, it started working just fine.
Similarly, if you wanted to use the STAThread attribute on a C# Main method, it would look like the code below.
Windows Forms require STA threading, so if you were to create a C# Winapp, you’d see code like this in Program.cs.
I don’t want to duplicate the existing documentation about STAThread and MTAThread, so I’ve included some links below that you can use to learn more.
- Bill Horst, VB IDE Test