使用ThreadStatic属性提供线程安全的数据访问
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 RequiresTraceAttribute
return 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!