Initializing ThreadStatic fields is a little tricky. In particular there is this caveat:
Do not specify initial values for fields marked with
ThreadStaticAttribute, because such initialization occurs only once,
when the class constructor executes, and therefore affects only one
thread.
in the MSDN Docs. What this means is that the thread running when the class is initialized gets that initial value you've defined in the field declaration, but all other threads will have a value of null. I think this is why your code is exhibiting the undesirable behavior described in your question.
A fuller explanation is in this blog.
(a snippet from the blog)
[ThreadStatic]
private static string Foo = "the foo string";
The ThreadStatic is initialized in the static constructor - which only
executes once. So only the very first thread is assigned "the foo
string" when the static constructor executes. When accessed in all
subsequent threads, Foo is left at the uninitalized null value.
The best way to work around this is to use a property to access the
Foo prop.
[ThreadStatic]
private static string _foo;
public static string Foo {
get {
if (_foo == null) {
_foo = "the foo string";
}
return _foo;
}
}
Note that there is no need for a lock in the static property, because each thread is acting upon the _foo
that is just for that thread. There can't be contention with other threads. This is covered in this question: ThreadStatic and Synchronization
Lazy<T>
it has thread safe options – JambalayaRngcryptoserviceprovider
which is ThreadSafe – Johnston