Skip to content

Commit 08f4dc0

Browse files
Update ThreadStatic example (#11094)
1 parent 866a957 commit 08f4dc0

File tree

5 files changed

+97
-279
lines changed

5 files changed

+97
-279
lines changed

snippets/csharp/System/ThreadStaticAttribute/Overview/Project.csproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
55
<TargetFramework>net6.0</TargetFramework>
6+
<Nullable>enable</Nullable>
67
</PropertyGroup>
7-
8+
89
</Project>

snippets/csharp/System/ThreadStaticAttribute/Overview/threadsafe2a.cs

+33-98
Original file line numberDiff line numberDiff line change
@@ -2,108 +2,43 @@
22
using System;
33
using System.Threading;
44

5-
public class Example
5+
class Program
66
{
7-
[ThreadStatic] static double previous = 0.0;
8-
[ThreadStatic] static double sum = 0.0;
9-
[ThreadStatic] static int calls = 0;
10-
[ThreadStatic] static bool abnormal;
11-
static int totalNumbers = 0;
12-
static CountdownEvent countdown;
13-
private static Object lockObj;
14-
Random rand;
15-
16-
public Example()
17-
{
18-
rand = new Random();
19-
lockObj = new Object();
20-
countdown = new CountdownEvent(1);
21-
}
7+
[ThreadStatic]
8+
private static string? _requestId;
229

23-
public static void Main()
24-
{
25-
Example ex = new Example();
26-
Thread.CurrentThread.Name = "Main";
27-
ex.Execute();
28-
countdown.Wait();
29-
Console.WriteLine("{0:N0} random numbers were generated.", totalNumbers);
30-
}
10+
static void Main()
11+
{
12+
Thread thread1 = new(ProcessRequest);
13+
Thread thread2 = new(ProcessRequest);
3114

32-
private void Execute()
33-
{
34-
for (int threads = 1; threads <= 10; threads++)
35-
{
36-
Thread newThread = new Thread(new ThreadStart(this.GetRandomNumbers));
37-
countdown.AddCount();
38-
newThread.Name = threads.ToString();
39-
newThread.Start();
40-
}
41-
this.GetRandomNumbers();
42-
}
15+
thread1.Start("REQ-001");
16+
thread2.Start("REQ-002");
4317

44-
private void GetRandomNumbers()
45-
{
46-
double result = 0.0;
18+
thread1.Join();
19+
thread2.Join();
4720

48-
for (int ctr = 0; ctr < 2000000; ctr++)
49-
{
50-
lock (lockObj) {
51-
result = rand.NextDouble();
52-
calls++;
53-
Interlocked.Increment(ref totalNumbers);
54-
// We should never get the same random number twice.
55-
if (result == previous) {
56-
abnormal = true;
57-
break;
58-
}
59-
else {
60-
previous = result;
61-
sum += result;
62-
}
63-
}
64-
}
65-
// get last result
66-
if (abnormal)
67-
Console.WriteLine("Result is {0} in {1}", previous, Thread.CurrentThread.Name);
68-
69-
Console.WriteLine("Thread {0} finished random number generation.", Thread.CurrentThread.Name);
70-
Console.WriteLine("Sum = {0:N4}, Mean = {1:N4}, n = {2:N0}\n", sum, sum/calls, calls);
71-
countdown.Signal();
72-
}
21+
Console.WriteLine("Main thread execution completed.");
22+
}
23+
24+
static void ProcessRequest(object? requestId)
25+
{
26+
// Assign the request ID to the thread-static field
27+
_requestId = requestId as string;
28+
29+
// Simulate request processing across multiple method calls
30+
PerformDatabaseOperation();
31+
PerformLogging();
32+
}
33+
34+
static void PerformDatabaseOperation()
35+
{
36+
Console.WriteLine($"Thread {Environment.CurrentManagedThreadId}: Processing DB operation for request {_requestId}");
37+
}
38+
39+
static void PerformLogging()
40+
{
41+
Console.WriteLine($"Thread {Environment.CurrentManagedThreadId}: Logging request {_requestId}");
42+
}
7343
}
74-
// The example displays output similar to the following:
75-
// Thread 1 finished random number generation.
76-
// Sum = 1,000,556.7483, Mean = 0.5003, n = 2,000,000
77-
//
78-
// Thread 6 finished random number generation.
79-
// Sum = 999,704.3865, Mean = 0.4999, n = 2,000,000
80-
//
81-
// Thread 2 finished random number generation.
82-
// Sum = 999,680.8904, Mean = 0.4998, n = 2,000,000
83-
//
84-
// Thread 10 finished random number generation.
85-
// Sum = 999,437.5132, Mean = 0.4997, n = 2,000,000
86-
//
87-
// Thread 8 finished random number generation.
88-
// Sum = 1,000,663.7789, Mean = 0.5003, n = 2,000,000
89-
//
90-
// Thread 4 finished random number generation.
91-
// Sum = 999,379.5978, Mean = 0.4997, n = 2,000,000
92-
//
93-
// Thread 5 finished random number generation.
94-
// Sum = 1,000,011.0605, Mean = 0.5000, n = 2,000,000
95-
//
96-
// Thread 9 finished random number generation.
97-
// Sum = 1,000,637.4556, Mean = 0.5003, n = 2,000,000
98-
//
99-
// Thread Main finished random number generation.
100-
// Sum = 1,000,676.2381, Mean = 0.5003, n = 2,000,000
101-
//
102-
// Thread 3 finished random number generation.
103-
// Sum = 999,951.1025, Mean = 0.5000, n = 2,000,000
104-
//
105-
// Thread 7 finished random number generation.
106-
// Sum = 1,000,844.5217, Mean = 0.5004, n = 2,000,000
107-
//
108-
// 22,000,000 random numbers were generated.
10944
// </Snippet1>

snippets/fsharp/System/ThreadStaticAttribute/Overview/threadsafe2a.fs

+21-85
Original file line numberDiff line numberDiff line change
@@ -2,95 +2,31 @@
22
open System
33
open System.Threading
44

5-
type Example() =
6-
[<ThreadStatic; DefaultValue>]
7-
static val mutable private previous : double
5+
type ThreadLocal() =
6+
[<ThreadStatic; DefaultValue>]
7+
static val mutable private requestId: string option
88

9-
[<ThreadStatic; DefaultValue>]
10-
static val mutable private sum : double
11-
12-
[<ThreadStatic; DefaultValue>]
13-
static val mutable private calls : int
9+
static member PerformLogging() =
10+
Console.WriteLine($"Thread {Environment.CurrentManagedThreadId}: Logging request {ThreadLocal.requestId.Value}")
1411

15-
[<ThreadStatic; DefaultValue>]
16-
static val mutable private abnormal : bool
17-
18-
static let mutable totalNumbers = 0
19-
static let countdown = new CountdownEvent(1)
20-
static let lockObj = obj ()
21-
let rand = Random()
12+
static member PerformDatabaseOperation() =
13+
Console.WriteLine($"Thread {Environment.CurrentManagedThreadId}: Processing DB operation for request {ThreadLocal.requestId.Value}")
2214

15+
static member ProcessRequest(reqId: obj) =
16+
ThreadLocal.requestId <- Some(reqId :?> string)
17+
ThreadLocal.PerformDatabaseOperation()
18+
ThreadLocal.PerformLogging()
2319

24-
member this.Execute() =
25-
for threads = 1 to 10 do
26-
let newThread = new Thread(ThreadStart this.GetRandomNumbers)
27-
countdown.AddCount()
28-
newThread.Name <- threads.ToString()
29-
newThread.Start()
30-
this.GetRandomNumbers()
31-
countdown.Wait()
32-
printfn $"{totalNumbers:N0} random numbers were generated."
20+
[<EntryPoint>]
21+
let main _ =
22+
let thread1 = Thread(ThreadStart(fun () -> ThreadLocal.ProcessRequest("REQ-001")))
23+
let thread2 = Thread(ThreadStart(fun () -> ThreadLocal.ProcessRequest("REQ-002")))
3324

34-
member _.GetRandomNumbers() =
35-
let mutable i = 0
36-
while i < 2000000 do
37-
lock lockObj (fun () ->
38-
let result = rand.NextDouble()
39-
Example.calls <- Example.calls + 1
40-
Interlocked.Increment &totalNumbers |> ignore
41-
// We should never get the same random number twice.
42-
if result = Example.previous then
43-
Example.abnormal <- true
44-
i <- 2000001 // break
45-
else
46-
Example.previous <- result
47-
Example.sum <- Example.sum + result )
48-
i <- i + 1
49-
// get last result
50-
if Example.abnormal then
51-
printfn $"Result is {Example.previous} in {Thread.CurrentThread.Name}"
52-
53-
printfn $"Thread {Thread.CurrentThread.Name} finished random number generation."
54-
printfn $"Sum = {Example.sum:N4}, Mean = {Example.sum / float Example.calls:N4}, n = {Example.calls:N0}\n"
55-
countdown.Signal() |> ignore
25+
thread1.Start()
26+
thread2.Start()
27+
thread1.Join()
28+
thread2.Join()
5629

57-
let ex = Example()
58-
Thread.CurrentThread.Name <- "Main"
59-
ex.Execute()
60-
61-
// The example displays output similar to the following:
62-
// Thread 1 finished random number generation.
63-
// Sum = 1,000,556.7483, Mean = 0.5003, n = 2,000,000
64-
//
65-
// Thread 6 finished random number generation.
66-
// Sum = 999,704.3865, Mean = 0.4999, n = 2,000,000
67-
//
68-
// Thread 2 finished random number generation.
69-
// Sum = 999,680.8904, Mean = 0.4998, n = 2,000,000
70-
//
71-
// Thread 10 finished random number generation.
72-
// Sum = 999,437.5132, Mean = 0.4997, n = 2,000,000
73-
//
74-
// Thread 8 finished random number generation.
75-
// Sum = 1,000,663.7789, Mean = 0.5003, n = 2,000,000
76-
//
77-
// Thread 4 finished random number generation.
78-
// Sum = 999,379.5978, Mean = 0.4997, n = 2,000,000
79-
//
80-
// Thread 5 finished random number generation.
81-
// Sum = 1,000,011.0605, Mean = 0.5000, n = 2,000,000
82-
//
83-
// Thread 9 finished random number generation.
84-
// Sum = 1,000,637.4556, Mean = 0.5003, n = 2,000,000
85-
//
86-
// Thread Main finished random number generation.
87-
// Sum = 1,000,676.2381, Mean = 0.5003, n = 2,000,000
88-
//
89-
// Thread 3 finished random number generation.
90-
// Sum = 999,951.1025, Mean = 0.5000, n = 2,000,000
91-
//
92-
// Thread 7 finished random number generation.
93-
// Sum = 1,000,844.5217, Mean = 0.5004, n = 2,000,000
94-
//
95-
// 22,000,000 random numbers were generated.
30+
Console.WriteLine("Main thread execution completed.")
31+
0
9632
// </Snippet1>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
</PropertyGroup>
7+
8+
</Project>

0 commit comments

Comments
 (0)