首页 > 代码库 > [ThreadStatic] dosen't work with instance fields

[ThreadStatic] dosen't work with instance fields

ThreadStatic 属性对于字段无效

最近使用RESHARPER,发现有这个提示,查了下资料

Occa­sion­ally you might want to make the value of a sta­tic or instance field local to a thread (i.e. each thread holds an inde­pen­dent copy of the field), what you need in this case, is a thread-local stor­age.

In C#, there are mainly two ways to do this.

Thread­Sta­tic

You can mark a field with the Thread­Sta­tic 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 eas­i­est way to imple­ment thread-local stor­age in C# it’s impor­tant to under­stand the lim­i­ta­tions here:

  • the Thread­Sta­tic attribute doesn’t work with instance fields, it com­piles 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 intro­duced a new class specif­i­cally for the thread-local stor­age 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:

  • val­ues are lazily eval­u­ated, the fac­tory func­tion eval­u­ates on the first call for each thread
  • you have more con­trol over the ini­tial­iza­tion of the field and is able to ini­tial­ize the field with a non-default value

Sum­mary

As you can see, using ThreadLocal<T> has some clear advan­tages over Thread­Sta­tic, though using 4.0 only fea­tures like ThreadLocal<T> means you have to tar­get your project at the .Net 4 frame­work and is there­fore not back­ward com­pat­i­ble with pre­vi­ous ver­sions of the framework.

It’s also worth not­ing that besides ThreadLocal<T> and Thread­Sta­tic you can also use Thread.GetData and Thread.SetData to fetch and store thread spe­cific data from and to a named Local­Data­S­toreS­lot though this is usu­ally cumbersome…

[ThreadStatic] dosen't work with instance fields