{"record":{"id":"5fe36feb76f5129a","repo":"dotnet/wpf","slug":"sr-format-sr-axrequiresapartmentthread-clsid-tostring","errorCode":null,"errorMessage":"SR.Format(SR.AxRequiresApartmentThread, clsid.ToString())","messagePattern":"SR\\.Format\\(SR\\.AxRequiresApartmentThread, clsid\\.ToString\\(\\)\\)","errorType":"exception","errorClass":"ThreadStateException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Interop/ActiveXHost.cs","lineNumber":85,"sourceCode":"            EventManager.RegisterClassHandler(typeof(ActiveXHost), AccessKeyManager.AccessKeyPressedEvent, new AccessKeyPressedEventHandler(OnAccessKeyPressed));\n\n            Control.IsTabStopProperty.OverrideMetadata(typeof(ActiveXHost), new FrameworkPropertyMetadata(true));\n\n            FocusableProperty.OverrideMetadata(typeof(ActiveXHost), new FrameworkPropertyMetadata(true));\n\n            EventManager.RegisterClassHandler(typeof(ActiveXHost), Keyboard.GotKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(OnGotFocus));\n            EventManager.RegisterClassHandler(typeof(ActiveXHost), Keyboard.LostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(OnLostFocus));\n            KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(ActiveXHost), new FrameworkPropertyMetadata(KeyboardNavigationMode.Once));\n        }\n\n\n        /// constructor for ActiveXHost\n        internal ActiveXHost(Guid clsid, bool fTrusted ) : base( fTrusted )\n        {\n            // What if the control is marked as free-threaded?\n            if (Thread.CurrentThread.GetApartmentState() is not ApartmentState.STA)\n            {\n                throw new ThreadStateException(SR.Format(SR.AxRequiresApartmentThread, clsid.ToString()));\n            }\n\n            _clsid = clsid;\n\n            // hookup so we are notified when loading is finished.\n            Initialized += new EventHandler(OnInitialized);\n        }\n\n\n        #endregion Constructors and Finalizers\n\n        //------------------------------------------------------\n        //\n        //  Protected Methods\n        //\n        //------------------------------------------------------\n\n        #region Protected Methods","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Interop/ActiveXHost.cs#L67-L103","documentation":"ActiveXHost (base of WindowsFormsHost-style interop controls) requires an STA thread because ActiveX controls must run in a single-threaded apartment. The constructor checks Thread.CurrentThread.GetApartmentState() and throws ThreadStateException if the hosting thread is not STA, including the control's CLSID in the message.","triggerScenarios":"Constructing an ActiveXHost-derived control (or a wrapped COM control like WebBrowser/WindowsFormsHost scenarios) on an MTA thread or a thread whose apartment state was never set (MTA by default on worker threads).","commonSituations":"Creating WPF/WinForms interop controls on background Task/ThreadPool threads, console apps that never set [STAThread] on Main, or COM server/test harnesses spinning plain threads to instantiate controls.","solutions":["Create the control on an STA thread: mark the entry point with [STAThread] or call Thread.SetApartmentState(ApartmentState.STA) before Thread.Start.","If using a background thread, create a dedicated Thread (not ThreadPool/Task) and set STA before instantiating the control.","Use a dispatcher/SynchronizationContext to marshal control creation onto the existing UI (STA) thread."],"exampleFix":"// before\nvar thread = new Thread(() => new ActiveXControl(clsid));\nthread.Start();\n// after\nvar thread = new Thread(() => new ActiveXControl(clsid));\nthread.SetApartmentState(ApartmentState.STA);\nthread.Start();","handlingStrategy":"validation","validationCode":"if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)\n    throw new InvalidOperationException(\"Control must be created on an STA thread\");\n// create control here","typeGuard":"bool CanCreateActiveXHost(Thread t) =>\n    t.GetApartmentState() == ApartmentState.STA;","tryCatchPattern":"try\n{\n    var control = new ActiveXControl(clsid);\n}\ncatch (ThreadStateException ex)\n{\n    // recreate on a dedicated STA thread or marshal to UI thread\n    Log(ex);\n}","preventionTips":["Always mark UI entry points with [STAThread].","Never create interop controls on ThreadPool/Task threads; use a dedicated STA Thread.","Assert apartment state in test setup for UI/interop tests."],"tags":["wpf","activex","threading","sta"],"backgroundTag":"thread-apartment-state","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}