Common Intermediate Language и системное программирование в Microsoft.Net. Макаров А.В - 134 стр.

UptoLike

относительных приоритетов Win32 API так, что при переносе на другие
платформы существует возможность предоставить их корректные анало-
ги. В .NET используются приоритеты Highest, AboveNormal, Normal,
BelowNormal и Lowest.
Когда .NET приложение начинает исполняться в среде Windows,
CLR создает внутренний пул потоков, используемый средой для реализа-
ции асинхронных операций ввода-вывода, вызова асинхронных процедур,
обработки таймеров и других целей. Потоки могут добавляться в пул по
мере надобности. Этот пул реализуется на основе пула потоков, управляе-
мого операционной системой (построенного на основе порта завершения
ввода-вывода). Для взаимодействия с пулом потоков предусмотрен класс
ThreadPool, и единственный объект, принадлежащий этому классу, созда-
ется CLR при запуске приложения. Все домены приложений в рамках од-
ного процесса используют общий пул потоков.
Разработчики могут использовать несколько статических методов
класса ThreadPool. Так, например, существует возможность связать внут-
ренний порт завершения ввода-вывода с файловым объектом, созданным
неуправляемым кодом, для обработки событий, связанных с завершением
ввода-вывода этим объектом (см. методы ThreadPool.BindHandle и описа-
ние порта завершения ввода-вывода в главе 7.1.1). Можно управлять чис-
лом потоков в пуле (методы GetAvailableThreads, GetMaxThreads,
GetMinThreads и SetMinThreads), можно ставить в очередь асинхронных вы-
зовов собственные процедуры (метод QueueUserWorkItem) и назначать про-
цедуры, которые будут вызываться при освобождении какого-либо объек-
та (метод RegisterWaitForSingleObject). Эти два метода имеют «безопас-
ные» и «небезопасные» (Unsafe...) версии; последние отличаются тем, что
в стеке вызовов асинхронных методов не будут присутствовать данные о
реальном контексте безопасности потока, поставившего в очередь этот
вызов, – в подобном случае будет использоваться контекст безопасности
самого пула потоков.
7.3.2. Асинхронный ввод-вывод
Для реализации асинхронного ввода-вывода в .NET предназначен
абстрактный класс System.IO.Stream. В этом классе определены абстракт-
ные синхронные методы чтения Read и записи Write, а также реализация
асинхронных методов BeginRead, EndRead, BeginWrite и EndWrite. Асин-
хронные методы реализованы с помощью обращения к синхронным опе-
рациям фоновыми потоками пула.
На основе абстрактного класса Stream в .NET Framework реализуют-
ся потомки, осуществляющие взаимодействие с разного рода потоками
данных. Так, например, System.IO.FileStream реализует операции с файла-
ми, System.IO.MemoryStream предоставляет возможность использования
Разработка параллельных приложений для ОС Windows
255
возобновить вызовом метода Thread.Resume. Также можно досрочно выве-
сти поток из состояния ожидания вызовом метода Thread.Interrupt.
Рис. 7.1. Состояния потока
Завершение функции потока нормальным образом переводит поток
в состояние «завершен» (Stopped), а досрочное прекращение работы вызо-
вом метода Thread.Abort переведет его в состояние «прерван» (Aborted).
Кроме того, .NET поддерживает несколько переходных состояний
(AbortRequested, StopRequested и SuspendRequested). Состояния потока в
общем случае могут комбинироваться, например, вполне корректно соче-
тание состояния ожидания (WaitSleepJoin) и какого-либо переходного,
скажем, AbortRequested.
Для выполнения задержек в ходе выполнения потока предназначены
два метода – Sleep, переводящий поток в состояние ожидания на заданное
время, и SpinWait, который выполняет некоторую задержку путем много-
кратных повторов внутреннего цикла. Этот метод дает высокую загрузку
процессора, однако позволяет реализовать очень короткие паузы. К сожа-
лению, продолжительность пауз зависит от производительности и загру-
женности процессора.
Для получения и задания приоритета потока используется свойство
Thread.Priority. Приоритеты потока в .NET базируются на подмножестве
254
CIL и системное программирование в Microsoft .NET
Создание объекта
Thread
Уничтожение
объекта Thread
Start() Suspend() Resume()
Interrupt() и завершение ожидания
Sleep(),
Join() и
переход к
ожиданию
return Abort()
Unstarted Suspended
WaitSleepJoin
Running
Stopped Aborted
254                                 CIL и системное программирование в Microsoft .NET   Разработка параллельных приложений для ОС Windows                   255


возобновить вызовом метода Thread.Resume. Также можно досрочно выве-                    относительных приоритетов Win32 API так, что при переносе на другие
сти поток из состояния ожидания вызовом метода Thread.Interrupt.                        платформы существует возможность предоставить их корректные анало-
                                                                                        ги. В .NET используются приоритеты Highest, AboveNormal, Normal,
               Создание объекта                                                         BelowNormal и Lowest.
                    Thread                                                                   Когда .NET приложение начинает исполняться в среде Windows,
                                                                                        CLR создает внутренний пул потоков, используемый средой для реализа-
                                                                                        ции асинхронных операций ввода-вывода, вызова асинхронных процедур,
                     Unstarted                             Suspended                    обработки таймеров и других целей. Потоки могут добавляться в пул по
                                                                                        мере надобности. Этот пул реализуется на основе пула потоков, управляе-
                                                                                        мого операционной системой (построенного на основе порта завершения
               Start()           Suspend()                Resume()                      ввода-вывода). Для взаимодействия с пулом потоков предусмотрен класс
                                                                                        ThreadPool, и единственный объект, принадлежащий этому классу, созда-
                      Running                  Interrupt() и завершение ожидания        ется CLR при запуске приложения. Все домены приложений в рамках од-
                                                                                        ного процесса используют общий пул потоков.
                                                       Sleep(),      WaitSleepJoin           Разработчики могут использовать несколько статических методов
          return                 Abort()
                                                       Join() и                         класса ThreadPool. Так, например, существует возможность связать внут-
                                                      переход к                         ренний порт завершения ввода-вывода с файловым объектом, созданным
        Stopped                     Aborted           ожиданию                          неуправляемым кодом, для обработки событий, связанных с завершением
                                                                                        ввода-вывода этим объектом (см. методы ThreadPool.BindHandle и описа-
                                                                                        ние порта завершения ввода-вывода в главе 7.1.1). Можно управлять чис-
                    Уничтожение                                                         лом потоков в пуле (методы GetAvailableThreads, GetMaxThreads,
                   объекта Thread                                                       GetMinThreads и SetMinThreads), можно ставить в очередь асинхронных вы-
                                                                                        зовов собственные процедуры (метод QueueUserWorkItem) и назначать про-
      Рис. 7.1. Состояния потока                                                        цедуры, которые будут вызываться при освобождении какого-либо объек-
                                                                                        та (метод RegisterWaitForSingleObject). Эти два метода имеют «безопас-
     Завершение функции потока нормальным образом переводит поток                       ные» и «небезопасные» (Unsafe...) версии; последние отличаются тем, что
в состояние «завершен» (Stopped), а досрочное прекращение работы вызо-                  в стеке вызовов асинхронных методов не будут присутствовать данные о
вом метода Thread.Abort переведет его в состояние «прерван» (Aborted).                  реальном контексте безопасности потока, поставившего в очередь этот
Кроме того, .NET поддерживает несколько переходных состояний                            вызов, – в подобном случае будет использоваться контекст безопасности
(AbortRequested, StopRequested и SuspendRequested). Состояния потока в                  самого пула потоков.
общем случае могут комбинироваться, например, вполне корректно соче-
тание состояния ожидания (WaitSleepJoin) и какого-либо переходного,                     7.3.2. Асинхронный ввод-вывод
скажем, AbortRequested.                                                                      Для реализации асинхронного ввода-вывода в .NET предназначен
     Для выполнения задержек в ходе выполнения потока предназначены                     абстрактный класс System.IO.Stream. В этом классе определены абстракт-
два метода – Sleep, переводящий поток в состояние ожидания на заданное                  ные синхронные методы чтения Read и записи Write, а также реализация
время, и SpinWait, который выполняет некоторую задержку путем много-                    асинхронных методов BeginRead, EndRead, BeginWrite и EndWrite. Асин-
кратных повторов внутреннего цикла. Этот метод дает высокую загрузку                    хронные методы реализованы с помощью обращения к синхронным опе-
процессора, однако позволяет реализовать очень короткие паузы. К сожа-                  рациям фоновыми потоками пула.
лению, продолжительность пауз зависит от производительности и загру-                         На основе абстрактного класса Stream в .NET Framework реализуют-
женности процессора.                                                                    ся потомки, осуществляющие взаимодействие с разного рода потоками
     Для получения и задания приоритета потока используется свойство                    данных. Так, например, System.IO.FileStream реализует операции с файла-
Thread.Priority. Приоритеты потока в .NET базируются на подмножестве                    ми, System.IO.MemoryStream предоставляет возможность использования