1 У метода FromAsync класса TaskScheduler имеются перегруженные версии, получающие
[55] AsyncResult, а также перегруженные версии, получающие делегатов для методов BeginXxx и EndXxx. По возможности постарайтесь избегать версии с IAsyncResult, потому что они менее эффективны.
Для любознательных: это делает метод GetResult класса TaskAwaiter.
[56] К счастью, компилятор не выдает предупреждения о том, что локальная переменная не используется в программе.
[57] Занятное наблюдение: когда я тестировал этот код на своей машине, загрузка процессора на моем 8-процессорном компьютере, естественно, доходила до 100 %. Так как все процессоры были заняты, машина нагревалась, и шум от вентилятора становился сильнее! После завершения обработки загрузка процессора снижалась, и вентилятор тоже затихал.
[58] Дополнительная информация по данной теме находится по адресу http://msdn.microsoft. com/ru-ru/library/bz9tc508.aspx.
[59] Windows-функция SuperFetch использует низкоприоритетные запросы ввода-вывода в своих интересах.
[60] Поле, к которому осуществляют доступ оба члена, помечается ключевым словом volatile, о котором мы поговорим чуть позже.
[61] Чуть дальше в этой главе показана программа, измеряющая производительность.
[62] Я считаю, что выделенная потоку память расходуется впустую, если поток не выполняет никакой полезной работы.
[63] В моей книге «Windows via C/C++» (Microsoft Press, 2007) этой теме посвящено несколько глав.
[64] Существуют также перегруженные версии методов Volatile Read и Volatile Write, работающие с типами: Boolean, (S)Byte, (U)Intl6, UInt32, (U)Int64, (U)IntPtr, Single, Double и T, где T — обобщенный тип с ограничением 'class' (ссылочные типы).
[65] Кстати, Microsoft Visual Basic не содержит встроенной семантики volatile.
[66] Код будет работать корректно, даже если вызвать метод m_ac.AboutToBeging(m_requests. Length) всего один раз перед циклом вместо вызова метода AboutToBegin внутри цикла.
[67] Очевидно, что из-за метода обратного вызова morpher метод Morph хуже в плане производительности. Чтобы исправить ситуацию, сделайте код подставляемым (inline), как в примере Maximum.
[68] При ожидании объекта Mutex поток не зацикливается, потому что код этого объекта находится в ядре. То есть проверка состояния объекта Mutex возможна только после перехода потока в ядро.
[69] Хотя класса AutoResetEventSlim не существует, во многих ситуациях можно обойтись конструированием объекта SemaphoreSlim с параметром maxCount равным единице.
[70] Кстати говоря, блокировку можно безопасно снять в блоке finally, если код блока try только читает состояние', не пытаясь его изменять (впрочем, это также приводит к снижению производительности).
[71] Код в файле Ch30-l-HybridThreadSync.cs является частью сопроводительного кода к данной книге. Вы можете загрузить его с сайта http://Wintellect.com/Books.
[72] Вместо класса Monitor можно воспользоваться чуть более быстрым классом SpinLock. Но при этом возможна ситуация, когда ресурсы процессора начнут тратиться впустую. И с моей точки зрения, класс SpinLock не настолько превосходит Monitor по скорости, чтобы оправдать его применение.
[73] Частично это связано с тем, что класс Monitor реализован на машинном, а не на управляемом коде.