Управляемые и неуправляемые потоки в Windows
Управление всеми потоками осуществляется посредством класса Thread , включая потоки, созданные средой CLR или созданные за пределами среды выполнения и входящие в управляемую среду для выполнения кода. Среда выполнения отслеживает в своем процессе все потоки, которые когда-либо выполняли код в управляемой среде. Другие потоки она не отслеживает. Потоки могут входить в управляемую среду выполнения посредством COM-взаимодействия (так как среда выполнения предоставляет управляемые объекты неуправляемой среде в качестве COM-объектов), функции COM DllGetClassObject и вызова неуправляемого кода.
Когда неуправляемый поток входит в среду выполнения, например, посредством вызываемой оболочки COM, система проверяет локальное хранилище потока данного потока для поиска внутреннего управляемого объекта Thread . Если он найден, среда выполнения уже оповещена об этом потоке. Если найти объект не удается, среда выполнения создает новый объект Thread и устанавливает его в локальном хранилище потока данного потока.
При использовании управляемых потоков Thread.GetHashCode является стабильным средством идентификации управляемого потока. В течение времени существования вашего потока он не будет конфликтовать со значением из любого другого потока независимо от того, из какого домена приложения вы получили это значение.
Сопоставление потоков Win32 с управляемыми потоками
В следующей таблице элементы потоков Win32 сопоставляются со своими ближайшими аналогами из среды выполнения. Обратите внимание, что такое сопоставление не означает идентичную функциональность. Например, TerminateThread не выполняет предложения finally , не освобождает ресурсы и не может быть запрещен. Однако Thread.Abort выполняет весь ваш код отката, освобождает все ресурсы и может быть отменен с помощью ResetAbort. Прежде чем делать предположения о функциональности, тщательно изучите документацию.
В Win32 | В среде CLR |
---|---|
CreateThread | Сочетание Thread и ThreadStart |
TerminateThread | Thread.Abort |
SuspendThread | Thread.Suspend |
ResumeThread | Thread.Resume |
Sleep | Thread.Sleep |
WaitForSingleObject в дескрипторе потока | Thread.Join |
ExitThread | Нет эквивалента |
GetCurrentThread | Thread.CurrentThread |
SetThreadPriority | Thread.Priority |
Нет эквивалента | Thread.Name |
Нет эквивалента | Thread.IsBackground |
Близко к CoInitializeEx (OLE32.DLL) | Thread.ApartmentState |
Управляемые потоки и подразделения COM
Управляемый поток может быть отмечен для указания того, что в нем будет размещаться однопотоковое или многопотоковое подразделение. (Дополнительные сведения об архитектуре потоков COM см. в разделе .Процессы, потоки и квартиры.) SetApartmentStateМетоды GetApartmentStateи TrySetApartmentState методы Thread класса возвращают и назначают состояние квартиры потока. Если состояние не задано, GetApartmentState возвращает ApartmentState.Unknown.
Свойство можно задать, только когда поток находится в состоянии ThreadState.Unstarted, и сделать это можно только один раз для потока.
Если состояние подразделения не задано до запуска потока, этот поток инициализируется в качестве многопотокового подразделения (MTA). Поток метода завершения и все потоки, управляемые ThreadPool , являются многопотоковыми подразделениями.
Внимание
Для кода запуска приложения единственный способ управления состоянием подразделения заключается в применении MTAThreadAttribute или STAThreadAttribute к процедуре точки входа.
Управляемые объекты, предоставляемые COM, ведут себя так, как если бы они агрегировали свободнопоточное маршализатор. Другими словами, их можно вызвать из любого подразделения COM в режиме свободного потока. В таком режиме не работают только управляемые объекты, производные от ServicedComponent или StandardOleMarshalObject.
В управляемом коде отсутствует поддержка SynchronizationAttribute , если только вы не используете контексты и контекстно-привязанные управляемые экземпляры. Если вы используете корпоративные службы, ваш объект должен быть производным от ServicedComponent (который сам является производным от ContextBoundObject).
Когда управляемый код вызывает COM-объекты, он всегда следует правилам COM. Другими словами, он выполняет вызов через прокси-серверы подразделения COM и оболочки контекста COM+ 1.0, как того требует OLE32.
Критические препятствия
Если поток выполняет неуправляемый вызов для операционной системы, которая заблокировала этот поток в неуправляемом коде, среда выполнения не берет на себя управление им для Thread.Interrupt или Thread.Abort. В случае с Thread.Abort среда выполнения помечает поток как Abort, приступая к управлению, когда он повторно входит в управляемый код. Вместо неуправляемой блокировки рекомендуется использовать управляемую блокировку. WaitHandle.WaitOne,WaitHandle.WaitAny, WaitHandle.WaitAll, Monitor.Enter, Monitor.TryEnter, Thread.Join, GC.WaitForPendingFinalizers и др. реагируют на Thread.Interrupt и Thread.Abort. Кроме того, если ваш поток находится в однопотоковом подразделении, все эти операции управляемой блокировки будут корректно выдавать сообщения в ваше подразделение, пока поток находится в заблокированном состоянии.
Потоки и волокна
Потоковая модель .NET не поддерживает волокна. Не следует вызывать неуправляемые функции, которые реализуется с использованием волокон. Такие вызовы могут привести к сбою среды выполнения .NET.