首页 > 代码库 > [ThreadStatic] dosen't work with instance fields
[ThreadStatic] dosen't work with instance fields
ThreadStatic 属性对于字段无效
最近使用RESHARPER,发现有这个提示,查了下资料
Occasionally you might want to make the value of a static or instance field local to a thread (i.e. each thread holds an independent copy of the field), what you need in this case, is a thread-local storage.
In C#, there are mainly two ways to do this.
ThreadStatic
You can mark a field with the ThreadStatic attribute:
1 2 3 4 5 | [ThreadStatic] public static int _x; … Enumerable.Range(1, 10).Select(i => new Thread(() => Console.WriteLine(_x++))).ToList() .ForEach(t => t.Start()); // prints 0 ten times |
Whilst this is the easiest way to implement thread-local storage in C# it’s important to understand the limitations here:
- the ThreadStatic attribute doesn’t work with instance fields, it compiles and runs but does nothing..
1 2 3 4 5 | [ThreadStatic] public int _x; … Enumerable.Range(1, 10).Select(i => new Thread(() => Console.WriteLine(_x++))).ToList() .ForEach(t => t.Start()); // prints 0, 1, 2, … 9 |
- field always start with the default value
1 2 3 4 5 | [ThreadStatic] public static int _x = 1; … Enumerable.Range(1, 10).Select(i => new Thread(() => Console.WriteLine(_x++))).ToList() .ForEach(t => t.Start()); // prints 0 ten times |
ThreadLocal<T>
C# 4 has introduced a new class specifically for the thread-local storage of data – the ThreadLocal<T> class:
1 2 3 4 | private readonly ThreadLocal< int > _localX = new ThreadLocal< int >(() => 1); … Enumerable.Range(1, 10).Select(i => new Thread(() => Console.WriteLine(_localX++))).ToList() .ForEach(t => t.Start()); // prints 1 ten times |
There are some bonuses to using the ThreadLocal<T> class:
- values are lazily evaluated, the factory function evaluates on the first call for each thread
- you have more control over the initialization of the field and is able to initialize the field with a non-default value
Summary
As you can see, using ThreadLocal<T> has some clear advantages over ThreadStatic, though using 4.0 only features like ThreadLocal<T> means you have to target your project at the .Net 4 framework and is therefore not backward compatible with previous versions of the framework.
It’s also worth noting that besides ThreadLocal<T> and ThreadStatic you can also use Thread.GetData and Thread.SetData to fetch and store thread specific data from and to a named LocalDataStoreSlot though this is usually cumbersome…
[ThreadStatic] dosen't work with instance fields