Как работает [ThreadStatic]
атрибут? Я предполагал, что компилятор испускает некоторый IL для заполнения / извлечения значения в TLS, но, глядя на разборку, похоже, что это не делается на этом уровне.
Что произойдет, если вы поместите его на нестатический член? У нас был разработчик, который допустил эту ошибку, а компилятор даже не выдает предупреждения.
Обновить
Ответ на второй вопрос здесь: ThreadStatic изменен с помощью Static C #
c#
static
threadstatic
Джошперри
источник
источник
public class SomeClass { public static MyContext myContext; ...
теперь сразу после захвата потока пула выполнитеSomeClass.myContext = new MyContext();
Ответы:
Семантика реализации статических потоков ниже уровня IL в jit-компиляторе .NET. Компиляторам, которые отправляют данные в IL, такие как VB.NET и C #, не нужно ничего знать о Win32 TLS, чтобы генерировать код IL, который может читать и записывать переменную с атрибутом ThreadStatic. Насколько известно C #, в этой переменной нет ничего особенного - это просто место для чтения и записи. Тот факт, что он имеет атрибут, не имеет значения для C #. C # нужно только знать, чтобы выдавать инструкции чтения или записи IL для этого имени символа.
«Тяжелая работа» выполняется основной средой CLR, которая отвечает за работу IL на конкретной аппаратной архитектуре.
Это также объясняет, почему размещение атрибута в несоответствующем (нестатическом) символе не вызывает реакции со стороны компилятора. Компилятор не знает, какая специальная семантика требуется атрибуту. Однако инструменты анализа кода, такие как FX / Cop, должны знать об этом.
Другой способ взглянуть на это: CIL определяет набор областей хранения: статическое (глобальное) хранилище, хранилище элементов и хранилище стека. TLS нет в этом списке, очень вероятно, потому что TLS не обязательно должен быть в этом списке. Если инструкций чтения и записи IL достаточно для доступа к TLS, когда символ помечен атрибутом TLS, почему IL должно иметь какое-либо специальное представление или обработку для TLS? Это не нужно.
источник
[ContextStatic]
атрибут распространяется и на этот случай (его название подразумевает, что он работает на основе контекста потока), но, вероятно, я ошибался в своем предположении. Я вижу в сети людей, которые говорят, что[ContextStatic]
атрибут используется с удаленным взаимодействием.Вы можете подумать, что поле, помеченное как ThreadStatic , прикреплено к потоку и его время жизни сопоставимо со временем жизни потока.
Таким образом, псевдокод
ThreadStatic
похож (по семантике) на привязку значения ключа к потоку:Thread.Current["MyClass.myVariable"] = 1; Thread.Current["MyClass.myvariable"] += 1;
но синтаксис немного проще:
class MyClass { [ThreadStatic] static int myVariable; } // .. then MyClass.myVariable = 1; MyClass.myVariable += 1;
Я считаю, что это игнорируется:
class A { [ThreadStatic] public int a; } [Test] public void Try() { var a1 = new A(); var a2 = new A(); a1.a = 5; a2.a = 10; a1.a.Should().Be.EqualTo(5); a2.a.Should().Be.EqualTo(10); }
Кроме того, стоит упомянуть, что
ThreadStatic
не требуется никакого механизма синхронизации по сравнению с обычными статическими полями (поскольку состояние не является общим).источник
"MyClass.myVariable"
, не так ли?TransactionScope
их хранения всякой всячины там для области ( referencesource.microsoft.com/#System.Transactions/System/... )[ThreadStatic] создает изолированные версии одной и той же переменной в каждом потоке.
Пример:
[ThreadStatic] public static int i; // Declaration of the variable i with ThreadStatic Attribute. public static void Main() { new Thread(() => { for (int x = 0; x < 10; x++) { i++; Console.WriteLine("Thread A: {0}", i); // Uses one instance of the i variable. } }).Start(); new Thread(() => { for (int x = 0; x < 10; x++) { i++; Console.WriteLine("Thread B: {0}", i); // Uses another instance of the i variable. } }).Start(); }
источник
[ThreadStatic]
Поля, отмеченные значком , создаются в локальном хранилище потока, поэтому у каждого потока есть собственная копия поля, т.е. область действия полей является локальной для потока.Доступ к полям TLS осуществляется через регистры сегментов gs / fs. Эти сегменты используются ядрами ОС для доступа к памяти, зависящей от потока. Компилятор .net не испускает IL для заполнения / получения значения в TLS. Это делается ядром ОС.
источник