Это более подробный ответ, который некоторые люди могут найти полезным.
Если вы хотите сделать это исключительно с использованием API существующего стандарта .NET, тогда ответ действительно «нет», и я объясню почему.Я также расскажу о том, как этого добиться, используя набор API-интерфейсов .NET Standard 2.0 и либо один API-интерфейс ОС, либо один API-интерфейс .NET Core 2.1.
Это правда, что, как правило, фиксированныйсопоставление «один к одному» между управляемыми потоками и собственными потоками не гарантируется на протяжении всего жизненного цикла управляемого приложения.Это основано на стандарте CLI Раздел I.12.3.1:
CLI управляет несколькими параллельными потоками управления (не обязательно такими же, как потоки, предоставляемые операционной системой хоста), несколькими управляемыми кучамии адресное пространство совместно используемой памяти.
Одна вещь, которая не очень четко сформулирована, состоит в том, содержится ли коллекция собственных потоков, используемых для запуска управляемых потоков, в одном и том же процессе или нескольких процессах.Но в стандарте CLI и документации .NET есть операторы, которые указывают, что все управляемое приложение живет в одном процессе ОС.Также мне неизвестно о какой-либо реализации, которая планирует управляемые потоки в нескольких процессах ОС.
Давайте сначала рассмотрим простой случай, когда существует только один управляемый поток и / или только один собственный поток.Этот случай можно легко обработать, установив сродство всего процесса с помощью свойства Process.ProcessorAffinity .Независимо от того, как этот отдельный управляемый поток сопоставлен с несколькими собственными потоками, или этот единственный собственный поток сопоставлен с несколькими управляемыми потоками, для всего управляемого приложения может быть только одно значение сходства.
В противном случае может бытьмножественные сходства.Собственный поток типа ProcessThread
предлагает свойство только для записи ProcessorAffinity .Тип управляемого потока Thread
не предлагает такого API.Тем не менее, он предлагает статический метод BeginThreadAffinity , который позволяет текущему управляемому потоку фиксировать свое сопоставление с любым собственным потоком, к которому он в данный момент сопоставлен, до тех пор, пока управляемый поток не вызовет EndThreadAffinity
.Обратите внимание, что BeginThreadAffinity
не является подсказкой для среды выполнения.Либо создается исключение, либо оно успешно возвращается с фиксированным отображением для текущего управляемого потока.Теперь, если мы можем получить текущий собственный поток, мы можем просто изменить его привязку к процессору, используя ProcessThread.ProcessorAffinity
.К сожалению, в отличие от получения текущего управляемого потока, нет стандартного управляемого API, который возвращает ссылку или идентификатор текущего собственного потока.Как вы можете видеть, мы можем добиться фиксированного сопоставления, используя только API .NET Standard 2.0, но нет никакого способа выяснить, какой собственный поток сопоставлен с каким управляемым потоком. Я не думаю, что естьхорошая техническая причина, почему бы не иметь такого API.
Один из способов - вызвать некоторый OS-зависимый API для получения идентификатора текущего собственного потока.В Windows это GetCurrentThreadId
из kernel32.dll
.Текущий управляемый поток может вызывать этот API для получения идентификатора текущего собственного потока.Затем ссылку на соответствующий объект ProcessThread
можно получить путем итерации по собственным потокам с использованием Process.GetCurrentProcess().Threads
и поиска объекта с совпадающим идентификатором.После этого ProcessThread.ProcessorAffinity
можно использовать для эффективной установки соответствия текущего управляемого потока.Обратите внимание, что, поскольку ProcessThread.ProcessorAffinity
является свойством только для записи, отсутствует .NET Standard 2.0 API, позволяющий восстановить старую привязку.Я не знаю, почему это только для записи.
Другой, гораздо более сложный способ - использовать Thread.GetCurrentProcessorId , который в настоящее время существует только в .NET Core 2.1 (последняя версия),Вы можете установить привязку каждого собственного потока к определенному процессору и проверить, какой управляемый поток в данный момент работает на этом процессоре.В конце концов, вы можете определить, какой управляемый поток сопоставлен с каким собственным потоком.
Хотя возможно добиться фиксированного сопоставления, как обсуждалось выше, мне кажется, что BeginThreadAffinity
не гарантирует, что каждый управляемый поток сопоставляется с уникальным собственным потоком.Таким образом, сопоставление один-к-одному не может быть достигнуто стандартным образом.
В .NET Core ProcessThread.ProcessorAffinity
реализовано только в Windows.На других ОС выдает PlatformNotSupportedException
.