{"record":{"id":"c19768e82e8a98da","repo":"dotnet/wpf","slug":"sr-oleservicescontext-threadmustbesta","errorCode":null,"errorMessage":"SR.OleServicesContext_ThreadMustBeSTA","messagePattern":"SR\\.OleServicesContext_ThreadMustBeSTA","errorType":"exception","errorClass":"ThreadStateException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/OleServicesContext.cs","lineNumber":91,"sourceCode":"    /// </summary>\n    internal static void EnsureThreadState()\n    {\n        // Poke the CurrentOleServicesContext to ensure it is created, this will throw if the current thread is not STA.\n        _ = CurrentOleServicesContext;\n    }\n\n    /// <summary>\n    ///  Call OLE Interop DoDragDrop().  Initiate OLE DragDrop.\n    /// </summary>\n    internal void OleDoDragDrop(\n        IComDataObject dataObject,\n        UnsafeNativeMethods.IOleDropSource dropSource,\n        int allowedEffects,\n        int[] finalEffect)\n    {\n        if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)\n        {\n            throw new ThreadStateException(SR.OleServicesContext_ThreadMustBeSTA);\n        }\n\n        InputManager inputManager = (InputManager)Dispatcher.CurrentDispatcher.InputManager;\n        inputManager?.InDragDrop = true;\n\n        try\n        {\n            UnsafeNativeMethods.DoDragDrop(dataObject, dropSource, allowedEffects, finalEffect);\n        }\n        finally\n        {\n            inputManager?.InDragDrop = false;\n        }\n    }\n\n    /// <summary>\n    ///  Call OLE Interop RegisterDragDrop()\n    /// </summary>","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/OleServicesContext.cs#L73-L109","documentation":"OleServicesContext's DoDragDrop path requires an STA (single-threaded apartment) thread because OLE drag-drop COM interfaces must run on an STA. If the current thread's apartment state is not STA, it throws ThreadStateException(SR.OleServicesContext_ThreadMustBeSTA) before invoking OLE.","triggerScenarios":"Calling DragDrop.DoDragDrop (via OleServicesContext.OleDoDragDrop) from a non-STA thread, e.g. a worker/MTA thread that initiates a drag operation.","commonSituations":"Starting drag-drop from a Task.Run/background thread, console or service code touching WPF drag APIs, or a thread created with default MTA state (Thread.SetApartmentState never called).","solutions":["Initiate drag-drop on the UI thread (Dispatcher.Invoke/BeginInvoke to marshal to the STA main thread).","If creating the thread yourself, call thread.SetApartmentState(ApartmentState.STA) before Thread.Start().","Ensure [STAThread] is present on the application's Main entry point so the main thread is STA."],"exampleFix":"// before\nTask.Run(() => DragDrop.DoDragDrop(source, data, DragDropEffects.Copy)); // MTA thread -> throws\n// after\nDispatcher.BeginInvoke(() => DragDrop.DoDragDrop(source, data, DragDropEffects.Copy));","handlingStrategy":"validation","validationCode":"if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)\n    throw new InvalidOperationException(\"DoDragDrop must run on an STA thread\"); // guard before calling","typeGuard":"static bool IsStaThread() => Thread.CurrentThread.GetApartmentState() == ApartmentState.STA;","tryCatchPattern":"try { DragDrop.DoDragDrop(depObj, dataObj, effects); }\ncatch (ThreadStateException ex) when (ex.Message.Contains(\"STA\")) { /* marshal to UI thread and retry */ }","preventionTips":["Only initiate drag-drop from the UI thread.","Keep [STAThread] on Main; never call WPF drag APIs from Task.Run or thread-pool code.","Call SetApartmentState(ApartmentState.STA) before starting custom threads that touch OLE."],"tags":["wpf","sta-thread","ole","drag-drop","threading"],"backgroundTag":"thread-interrupted","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}