{"id":4523,"date":"2008-03-24T15:47:00","date_gmt":"2008-03-24T15:47:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/2008\/03\/24\/stathread-vs-mtathread-whorst\/"},"modified":"2024-07-05T14:26:28","modified_gmt":"2024-07-05T21:26:28","slug":"stathread-vs-mtathread-whorst","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/stathread-vs-mtathread-whorst\/","title":{"rendered":"STAThread vs. MTAThread (WHorst)"},"content":{"rendered":"<p class=\"MsoNormal\"><font face=\"Times New Roman\" size=\"3\">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.<\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Times New Roman\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font face=\"Times New Roman\" size=\"3\">I started with a C# application someone else had written.<span>&nbsp; <\/span>I&rsquo;ll call it &ldquo;DeltaEngine&rdquo; for the purpose of this post.<span>&nbsp; <\/span>DeltaEngine calls into a native assembly and handles certain events from it.<\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Times New Roman\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font face=\"Times New Roman\" size=\"3\">I created a solution where I referenced DeltaEngine as a library project, and called into it from a VB project.<span>&nbsp; <\/span>I&rsquo;ll call this project &ldquo;VBApp&rdquo;.<span>&nbsp; <\/span>So, the reference structure looks like this:<\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Times New Roman\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font face=\"Times New Roman\" size=\"3\">VBApp (VB) -&gt; DeltaEngine (C#) -&gt; NativeCode<\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Times New Roman\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font face=\"Times New Roman\" size=\"3\">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.<span>&nbsp; <\/span>However, I noticed if I made the exact same calls with DeltaEngine as the startup project, it handled the event as expected.<span>&nbsp; <\/span>I spent a lot of time trying to figure this out and was completely stumped.<\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Times New Roman\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font face=\"Times New Roman\" size=\"3\">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.<span>&nbsp; <\/span>Because DeltaEngine was originally developed with a C# project as the startup application, it assumed MTA threading.<span>&nbsp; <\/span>Since I started calling the code from a VB startup project, I was running it with STA threading, without realizing it.<span>&nbsp; <\/span>Because of this, the DeltaEngine code started waiting for the event after it had already been raised, so it waited indefinitely.<span>&nbsp; <\/span>If I set DeltaEngine as the startup project and made the same calls, it would use MTA threading and work as expected.<\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Times New Roman\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p><font face=\"Times New Roman\" size=\"3\"><\/p>\n<p class=\"MsoNormal\">The fix was to add the MTAThreadAttribute to my Sub Main in VBApp.<span>&nbsp; <\/span>After this, it started working just fine.<\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\"><span>&lt;MTAThread&gt; Sub Main()<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">Similarly, if you wanted to use the STAThread attribute on a C# Main method, it would look like the code below.<span>&nbsp; <\/span><\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\"><span>[STAThread]<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>static void Main()<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">Windows Forms require STA threading, so if you were to create a C# Winapp, you&rsquo;d see code like this in Program.cs.<\/p>\n<p><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Times New Roman\" size=\"3\"><\/font>&nbsp;<\/p>\n<p class=\"MsoNormal\"><font face=\"Times New Roman\" size=\"3\">I don&rsquo;t want to duplicate the existing documentation about STAThread and MTAThread, so I&rsquo;ve included some links below that you can use to learn more.<\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Times New Roman\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><b><font size=\"3\"><font face=\"Times New Roman\">STAThreadAttribute<\/p>\n<p><\/font><\/font><\/b><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Times New Roman\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/system.stathreadattribute(VS.71).aspx\"><font face=\"Times New Roman\" size=\"3\">http:\/\/msdn2.microsoft.com\/en-us\/library\/system.stathreadattribute(VS.71).aspx<\/font><\/a><\/p>\n<p class=\"MsoNormal\"><a href=\"http:\/\/blogs.msdn.com\/jfoscoding\/archive\/2005\/04\/07\/406341.aspx\"><font face=\"Times New Roman\" size=\"3\">http:\/\/blogs.msdn.com\/jfoscoding\/archive\/2005\/04\/07\/406341.aspx<\/font><\/a><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Times New Roman\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><b><font size=\"3\"><font face=\"Times New Roman\">MTAThreadAttribute<\/p>\n<p><\/font><\/font><\/b><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Times New Roman\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/system.mtathreadattribute(VS.71).aspx\"><font face=\"Times New Roman\" size=\"3\">http:\/\/msdn2.microsoft.com\/en-us\/library\/system.mtathreadattribute(VS.71).aspx<\/font><\/a><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Times New Roman\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font face=\"Times New Roman\" size=\"3\">&#8211; Bill Horst, VB IDE Test<\/font><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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. &nbsp; I started with a C# application someone else had written.&nbsp; I&rsquo;ll call it &ldquo;DeltaEngine&rdquo; for the purpose of this post.&nbsp; DeltaEngine calls into a native assembly and [&hellip;]<\/p>\n","protected":false},"author":260,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[192,195],"tags":[41],"class_list":["post-4523","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-featured","category-visual-basic","tag-bill-horst"],"acf":[],"blog_post_summary":"<p>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. &nbsp; I started with a C# application someone else had written.&nbsp; I&rsquo;ll call it &ldquo;DeltaEngine&rdquo; for the purpose of this post.&nbsp; DeltaEngine calls into a native assembly and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/4523","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/260"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=4523"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/4523\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=4523"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=4523"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=4523"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}