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 реализован на машинном, а не на управляемом коде.