Ответ 1
Инициализация полей ThreadStatic немного сложнее. В частности, есть такая оговорка:
Не указывайте начальные значения для полей, помеченных ThreadStaticAttribute, потому что такая инициализация происходит только один раз, когда выполняется конструктор класса, и, следовательно, влияет только на один поток.
в документах MSDN. Это означает, что поток, выполняемый при инициализации класса, получает начальное значение, которое вы определили в объявлении поля, но все остальные потоки будут иметь значение null. Я думаю, именно поэтому ваш код демонстрирует нежелательное поведение, описанное в вашем вопросе.
Более полное объяснение в этом блоге.
(фрагмент из блога)
[ThreadStatic]
private static string Foo = "the foo string";
ThreadStatic инициализируется в статическом конструкторе, который выполняется только один раз. Таким образом, только самому первому потоку назначается "строка foo" при выполнении статического конструктора. При обращении ко всем последующим потокам, Foo остается с неинициализированным нулевым значением.
Лучший способ обойти это - использовать свойство для доступа к Foo.
[ThreadStatic]
private static string _foo;
public static string Foo {
get {
if (_foo == null) {
_foo = "the foo string";
}
return _foo;
}
}
Обратите внимание, что нет необходимости в блокировке статического свойства, потому что каждый поток действует на _foo
который предназначен только для этого потока. Там не может быть спор с другими потоками. Это покрыто этим вопросом: ThreadStatic и Синхронизация