dotnet/wpf · error · InvalidOperationException
SR.ThreadAlreadyStarted
Error message
SR.ThreadAlreadyStarted
What it means
XamlBackgroundReader.StartThread starts a single background read thread; if _thread is already created it throws InvalidOperationException(SR.ThreadAlreadyStarted). Each reader instance may only start its background thread once.
Solutions
- Call StartThread exactly once per reader instance; create a new XamlBackgroundReader for a fresh read cycle.
- Guard the call: only invoke StartThread when the thread has not been started yet.
- Move StartThread to a single construction/initialization point rather than call sites scattered across code.
- Catch InvalidOperationException for ThreadAlreadyStarted if double-start is possible in your flow.
Example fix
// before
reader.StartThread("xaml");
reader.StartThread("xaml-retry"); // throws
// after
if (readerStarted) reader = new XamlBackgroundReader(...);
reader.StartThread("xaml");
readerStarted = true; Defensive patterns
Strategy: validation
Validate before calling
if (readerThreadStarted) throw new InvalidOperationException("StartThread already called on this XamlBackgroundReader.");
reader.StartThread("xaml");
readerThreadStarted = true; Try / catch
try { reader.StartThread(name); } catch (InvalidOperationException ex) when (/* ThreadAlreadyStarted */) { /* reuse existing thread or recreate reader */ } Prevention
- Call StartThread once per reader instance
- Centralize reader initialization
- Recreate the reader for each new parse run
When it happens
Trigger: Calling StartThread(name) twice on the same XamlBackgroundReader instance, e.g. calling it manually after the reader already auto-started, or calling it again after a prior successful start in retry logic.
Common situations: Re-initializing a reader that was reused across parse runs; wrapper layers and unit helpers both calling StartThread; code that retries StartThread after an unrelated failure assuming the thread never launched.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- SR.DefaultAttachablePropertyStoreCannotAddInstance
- ' '.' ' is a property without a getter and is not a valid…
- ' '.' ' is a property without a getter and is not a valid…
- ' '.' ' is a property without a getter and is not a valid…
- ' ' is not a valid XAML member name.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/ebcc7538c8850af5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlBackgroundReader.cs:87
xamlNodeNextDelegate = new XamlNodeNextDelegate(Next);
}
_internalReader = new ReaderDelegate(_wrappedReader.SchemaContext, xamlNodeNextDelegate, _wrappedReaderHasLineInfo);
// Standin so it won't start null
_currentNode = new XamlNode(XamlNode.InternalNodeType.StartOfStream);
}
public void StartThread()
{
StartThread("XAML reader thread");
}
public void StartThread(string threadName)
{
if (_thread is not null)
{
throw new InvalidOperationException(SR.ThreadAlreadyStarted);
}
ParameterizedThreadStart start = new ParameterizedThreadStart(XamlReaderThreadStart);
_thread = new Thread(start)
{
Name = threadName
};
_thread.Start();
}
// The "ThreadStart" function
private void XamlReaderThreadStart(object none)
{
try
{
InterruptableTransform(_wrappedReader, _writer, true);
}
catch (Exception ex)View on GitHub (pinned to 81131a70a4)