ThreadStatic是一个C#属性,用于为每个线程提供独立的静态字段。使用它可以让每个线程拥有该字段的独立副本,避免线程之间的共享
用途
- 线程独立数据:每个线程有独立的数据副本,彼此不干扰
- 性能优化:在多线程环境中减少锁的使用,因为每个线程访问自己的数据
- 线程安全:自动提供线程安全的数据访问
举例
using System;
using System.Threading.Tasks;class Program
{[ThreadStatic]private static int _threadSpecificData;static async Task Main(){var task1 = Task.Run(() =>{_threadSpecificData = 42;Console.WriteLine($"Task 1: {_threadSpecificData}");});var task2 = Task.Run(() =>{_threadSpecificData = 84;Console.WriteLine($"Task 2: {_threadSpecificData}");});await Task.WhenAll(task1, task2);}
}
运行结果:
Task 1: 42
Task 2: 84
实际项目应用
以下是Dynamo项目TraceUtils类
using System;
using System.Threading.Tasks;
/// <summary>
/// Utility class to Get/Set TraceData
/// </summary>
public static class TraceUtils
{internal const string __TEMP_REVIT_TRACE_ID = "{0459D869-0C72-447F-96D8-08A7FB92214B}-REVIT";// ReSharper restore InconsistentNaming[ThreadStatic] private static Dictionary<string, string> _localStorageSlot;internal static Dictionary<string, string> LocalStorageSlot{get{return _localStorageSlot ?? (_localStorageSlot = new Dictionary<string, string>());}set{_localStorageSlot = value;}}/// <summary>/// Returns a list of the keys bound to trace elements/// This should be extracted from the attribute on the methods/// </summary>/// <returns></returns>internal static List<String> TEMP_GetTraceKeys(){//TODO:Luke Extract this from RequiresTraceAttributereturn new List<string>() { __TEMP_REVIT_TRACE_ID };}/// <summary>/// Clear a specific key/// </summary>/// <param name="key"></param>internal static void ClearTLSKey(string key){LocalStorageSlot.Remove(key);}/// <summary>/// Clear the named slots for all the know keys/// </summary>internal static void ClearAllKnownTLSKeys(){LocalStorageSlot.Clear();}/// <summary>/// Returns the data that is bound to a particular key/// </summary>/// <param name="key"></param>/// <returns></returns>public static string GetTraceData(string key){string data;if (!LocalStorageSlot.TryGetValue(key, out data)){return null;}else{return data;}}/// <summary>/// Set the data bound to a particular key/// </summary>/// <param name="key"></param>/// <param name="value"></param>public static void SetTraceData(string key, string value){if (LocalStorageSlot.ContainsKey(key)){LocalStorageSlot[key] = value;}else{LocalStorageSlot.Add(key, value);}}
}
class Program
{static async Task Main(string[] args){var task1 = Task.Run(() =>{TraceUtils.SetTraceData("Task1Key", "Task1Data");Console.WriteLine($"Task 1: {TraceUtils.GetTraceData("Task1Key")}");});var task2 = Task.Run(() =>{TraceUtils.SetTraceData("Task2Key", "Task2Data");Console.WriteLine($"Task 2: {TraceUtils.GetTraceData("Task2Key")}");});await Task.WhenAll(task1, task2);}
}
运行结果:
Task 1: Task1Data
Task 2: Task2Data
参考
- https://github.com/DynamoDS/Dynamo.git