Помеченные поля С# ThreadStaticAttribute автоматически освобождаются, когда поток умирает?
Я обнаружил "ThreadStaticAttribute", и у меня есть много вопросов об этом:
все мои предыдущие зависящие от потока статические данные были реализованы как статический словарь, который TKey является Thread, и когда я хотел получить к нему доступ, я использовал Thread.CurrentThread и это работает. Но для этого требуется mantainance, потому что, если поток умирает, я должен удалить соответствующую запись из словаря. И мне также нужно учитывать безопасность потоков и многое другое.
Используя ThreadStaticAttribute, все эти вопросы, похоже, решаются, но я должен быть уверен в этом. Мои вопросы: мне нужно удалить захват экземпляра пометкой "ThreadStaticAttribute", каким-то образом, до того, как поток погибнет? Где находится информация об этом поле? Это в экземпляре объекта Thread или что-то в этом роде, так что, когда он больше не используется, сборщик мусора автоматически отбрасывает его? Существуют ли штрафы за производительность? Какие? Это быстрее, чем использование коллекции Keyed, как я делал?
Пожалуйста, мне нужно уточнить, как работает ThreadStaticAttribute.
Спасибо.
Ответы
Ответ 1
Нет, вам не нужно удалять экземпляры справки о значениях в поле, помеченном ThreadStatic
. Сборщик мусора автоматически подберет их, когда и поток, и объект больше не будут доступны корневыми объектами.
Единственное исключение здесь, если значение реализует IDisposable
, и вы хотите активно распоряжаться им. В общем, это сложная проблема для решения по ряду причин. Намного проще не иметь значений, которые реализуют IDisposable
и находятся в поле ThreadStatic
.
Что касается того, где это поле фактически хранится, оно несколько не имеет значения. Все, что вам нужно беспокоиться, это то, что он будет вести себя как любой другой объект в .Net. Единственными двумя отличиями в поведении являются
- Поле будет ссылаться на другое значение для каждого потока доступа.
- Инициализатор для поля будет запускаться только один раз (на практике это плохая идея иметь).
Ответ 2
Пометка статической переменной-члена как [ThreadStatic] сообщает компилятору о ее распределении в области памяти потоков (например, где выделен стек потока), а не в глобальной области памяти. Таким образом, каждый поток будет иметь свою собственную копию (которая, как гарантируется, будет инициализирована значением по умолчанию для этого типа, например: null, 0, false и т.д., Не используйте инициализаторы в строке, поскольку они будут инициализировать только один поток).
Итак, когда поток уходит, так же как и область памяти, освобождая ссылку. Конечно, если это требует более быстрого удаления (открытые потоки файлов и т.д.) Вместо того, чтобы ждать фоновой сборки мусора, вам может потребоваться убедиться, что вы сделаете это до выхода потока.
Возможно, существует ограничение на доступное пространство [ThreadStatic], но оно должно быть достаточным для нормального использования. Он должен быть несколько быстрее, чем доступ к коллекции с ключом (и более легко поточно-безопасный), и я думаю, что это сопоставимо с доступом к обычной статической переменной.
Исправление: С тех пор я слышал, что доступ к переменным ThreadStatic несколько медленнее, чем доступ к обычным статическим переменным. Я не уверен, что даже на самом деле быстрее, чем доступ к коллекции с ключом, но он предотвращает проблемы с сиротами (это был ваш вопрос) и нуждался в блокировке для обеспечения безопасности потоков, что усложняло бы подход, основанный на сборке.