Concurrency and Source Panels
Thread Local Context
Give each thread its own context value before storing a shared summary.
thread local
`ThreadLocal<T>` stores a separate value for each thread while the main thread reads ordinary shared results after `Join`.
Thread Local Context
ThreadLocalContext.cs
Replay: real traced execution (multi-file project)
using System;
using System.Threading;
class Program
{
static readonly ThreadLocal<int> WorkerScore = new ThreadLocal<int>(() => 0);
static int boost;
static int alphaResult;
static int betaResult;
static void AlphaWorker()
{
WorkerScore.Value = boost + 10;
alphaResult = WorkerScore.Value;
}
static void BetaWorker()
{
WorkerScore.Value = boost + 20;
betaResult = WorkerScore.Value;
}
static void Main()
{
int extra = 3;
boost = extra;
Thread alpha = new Thread(AlphaWorker);
Thread beta = new Thread(BetaWorker);
alpha.Start();
beta.Start();
alpha.Join();
beta.Join();
int total = alphaResult + betaResult;
Console.WriteLine($"extra={extra}");
Console.WriteLine($"total={total}");
}
}
using System;
using System.Threading;
class Program
{
static readonly ThreadLocal<int> WorkerScore = new ThreadLocal<int>(() => 0);
static int boost;
static int alphaResult;
static int betaResult;
static void AlphaWorker()
{
WorkerScore.Value = boost + 10;
alphaResult = WorkerScore.Value;
}
static void BetaWorker()
{
WorkerScore.Value = boost + 20;
betaResult = WorkerScore.Value;
}
static void Main()
{
int extra = 1;
boost = extra;
Thread alpha = new Thread(AlphaWorker);
Thread beta = new Thread(BetaWorker);
alpha.Start();
beta.Start();
alpha.Join();
beta.Join();
int total = alphaResult + betaResult;
Console.WriteLine($"extra={extra}");
Console.WriteLine($"total={total}");
}
}
using System;
using System.Threading;
class Program
{
static readonly ThreadLocal<int> WorkerScore = new ThreadLocal<int>(() => 0);
static int boost;
static int alphaResult;
static int betaResult;
static void AlphaWorker()
{
WorkerScore.Value = boost + 10;
alphaResult = WorkerScore.Value;
}
static void BetaWorker()
{
WorkerScore.Value = boost + 20;
betaResult = WorkerScore.Value;
}
static void Main()
{
int extra = 7;
boost = extra;
Thread alpha = new Thread(AlphaWorker);
Thread beta = new Thread(BetaWorker);
alpha.Start();
beta.Start();
alpha.Join();
beta.Join();
int total = alphaResult + betaResult;
Console.WriteLine($"extra={extra}");
Console.WriteLine($"total={total}");
}
}
extra ← 3, boost ← 3, alpha ← System.Threading.Thread, beta ← System.Threading.Thread
23static void Main()24{25 int extra→ 3 = 3; //@extra=1, 726 boost→ 3 = extra3;2728 Thread alpha→ System.Threading.Thread = new Thread(AlphaWorker);29 Thread beta→ System.Threading.Thread = new Thread(BetaWorker);3031 alphaSystem.Threading.Thread.Start();32 beta.Start();alphaResult ← 13
11static void AlphaWorker()12{13 WorkerScore.Value = boost3 + 10;14 alphaResult→ 13 = WorkerScore.Value;15}alpha.Start();
31alphaSystem.Threading.Thread.Start();32betaSystem.Threading.Thread.Start();3334alphaSystem.Threading.Thread.Join();35betaSystem.Threading.Thread.Join();betaResult ← 23
17static void BetaWorker()18{19 WorkerScore.Value = boost3 + 20;20 betaResult→ 23 = WorkerScore.Value;21}total ← 36
34 alpha.Join();35 betaSystem.Threading.Thread.Join();3637 int total→ 36 = alphaResult13 + betaResult23;38 Console.WriteLine($"extra={extra3}");39 Console.WriteLine($"total={total36}");40}outputextra=3 total=36
extra ← 1, boost ← 1, alpha ← System.Threading.Thread, beta ← System.Threading.Thread
23static void Main()24{25 int extra→ 1 = 1;26 boost→ 1 = extra1;2728 Thread alpha→ System.Threading.Thread = new Thread(AlphaWorker);29 Thread beta→ System.Threading.Thread = new Thread(BetaWorker);3031 alphaSystem.Threading.Thread.Start();32 betaSystem.Threading.Thread.Start();3334 alphaSystem.Threading.Thread.Join();35 beta.Join();static void AlphaWorker()
11static void AlphaWorker()12{13 WorkerScore.Value = boost1 + 10;14 alphaResult = WorkerScore.Value;alphaResult ← 11, betaResult ← 21
12{13 WorkerScore.Value = boost1 + 10;14 alphaResult→ 11 = WorkerScore.Value;15}1617static void BetaWorker()18{19 WorkerScore.Value = boost1 + 20;20 betaResult→ 21 = WorkerScore.Value;21}total ← 32
34 alphaSystem.Threading.Thread.Join();35 betaSystem.Threading.Thread.Join();3637 int total→ 32 = alphaResult11 + betaResult21;38 Console.WriteLine($"extra={extra1}");39 Console.WriteLine($"total={total32}");40}outputextra=1 total=32
extra ← 7, boost ← 7, alpha ← System.Threading.Thread, beta ← System.Threading.Thread
23static void Main()24{25 int extra→ 7 = 7;26 boost→ 7 = extra7;2728 Thread alpha→ System.Threading.Thread = new Thread(AlphaWorker);29 Thread beta→ System.Threading.Thread = new Thread(BetaWorker);3031 alphaSystem.Threading.Thread.Start();32 betaSystem.Threading.Thread.Start();3334 alphaSystem.Threading.Thread.Join();35 beta.Join();static void AlphaWorker()
11static void AlphaWorker()12{13 WorkerScore.Value = boost7 + 10;14 alphaResult = WorkerScore.Value;alphaResult ← 17, betaResult ← 27
12{13 WorkerScore.Value = boost7 + 10;14 alphaResult→ 17 = WorkerScore.Value;15}1617static void BetaWorker()18{19 WorkerScore.Value = boost7 + 20;20 betaResult→ 27 = WorkerScore.Value;21}total ← 44
34 alphaSystem.Threading.Thread.Join();35 betaSystem.Threading.Thread.Join();3637 int total→ 44 = alphaResult17 + betaResult27;38 Console.WriteLine($"extra={extra7}");39 Console.WriteLine($"total={total44}");40}outputextra=7 total=44