Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start thread pool worker threads in the default execution context #46181

Merged
merged 10 commits into from
Dec 19, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ internal void ThreadStart(object? obj)
_startArg = obj;

ExecutionContext? context = _executionContext;
if (context != null)
if (context != null && !context.IsDefault)
{
ExecutionContext.RunInternal(context, s_threadStartContextCallback, this);
}
Expand All @@ -87,7 +87,7 @@ internal void ThreadStart()
Debug.Assert(_start is ThreadStart);

ExecutionContext? context = _executionContext;
if (context != null)
if (context != null && !context.IsDefault)
{
ExecutionContext.RunInternal(context, s_threadStartContextCallback, this);
}
Expand Down Expand Up @@ -222,8 +222,7 @@ public void Start()
Debug.Assert(_delegate.Target is ThreadHelper);
var t = (ThreadHelper)_delegate.Target;

ExecutionContext? ec = ExecutionContext.Capture();
t.SetExecutionContextHelper(ec);
t.SetExecutionContextHelper(CurrentThread._executionContext);
kouvel marked this conversation as resolved.
Show resolved Hide resolved
}

StartInternal();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,10 +288,28 @@ private static bool TryCreateWorkerThread()
{
try
{
Thread workerThread = new Thread(WorkerThreadStart);
workerThread.IsThreadPoolThread = true;
workerThread.IsBackground = true;
workerThread.Start();
// Starting a new thread transfers the current execution context to the new thread. Worker threads must
// start in the default context, so switch contexts temporarily if necessary.
Thread currentThread = Thread.CurrentThread;
ExecutionContext? previousExecutionContext = currentThread._executionContext;
currentThread._executionContext = null;

try
{
Thread workerThread = new Thread(WorkerThreadStart);
workerThread.IsThreadPoolThread = true;
workerThread.IsBackground = true;
workerThread.Start();
}
catch
{
// Note: we have a "catch" rather than a "finally" because we want to stop the first pass of EH here.
// That way we can restore the previous context before any of our callers' EH filters run.
currentThread._executionContext = previousExecutionContext;
throw;
}

currentThread._executionContext = previousExecutionContext;
}
catch (ThreadStartException)
{
Expand All @@ -301,6 +319,7 @@ private static bool TryCreateWorkerThread()
{
return false;
}

return true;
}
}
Expand Down