[31] Сериализация графа объекта в поток в памяти

[32] Сериализация всего состояния приложения formatter.Serialize(stream, s_customers); formatter.Serialize(stream, spendingOrders); formatter.Serialize(stream, sprocessedOrders);

}

Метод, используемый для восстановления состояния приложения, выглядит примерно так:

private static void RestoreApplicationState(Stream stream) {

// Конструирование модуля форматирования сериализации

1 Применение настраиваемого атрибута System.Runtime.Serialization.OnDeserialized является более предпочтительным в случае вызова метода при десериализации объекта, чем реализация типом метода On Deserialization интерфейса System.Runtime.Serialization.

[34] DeserializationCallback.

[35] Байтовый тип со знаком в WinRT не поддерживается.

[36] Абстракция данных обычно поддерживается принудительно, поскольку классы WinRT не могут иметь открытых полей.

[37] Перечисления тоже допустимы, поскольку они фактически являются 32-разрядными числами.

[38] Например, из этого следует, что API не может содержать такие методы, как Sort класса System. Array. Интересно, что все языки (С, C++, С#, Visual Basic и JavaScript) поддерживают передачу элементов массива в обоих направлениях, а система типов WinRT такой возможности не дает.

[39] Чтобы получить дополнительную информацию по этой теме, откройте страницу http:// msdn.microsoft.com/en-us/library/windows/apps/hh995050.aspx и загрузите документ CLRandtheWindowsRuntime.docx.

[40] Интерфейс IAsyncInfo предоставляет свойство Status, которое содержит значение, переданное в параметре status метода обратного вызова. Так как параметр передается по значению, обращение к параметру (вместо запроса свойства Status) улучшит производительность приложения, потому что обращение к свойству приводит к вызову функции WinRT API через RCW.

[41] Библиотеки для C# и большинства других управляемых языков программирования не имеют метода DllMain, поэтому управляемые DLL-библиотеки не получают уведомлений DLL THREAD ATTACH и DLL THREAD DETACH. Что же касается неуправляемых библиотек, то при помощи Win32-функции DisableThreadLibraryCalls они могут отключать режим получения уведомлений. К сожалению, многие разработчики неуправляемого кода не используют эту функцию просто потому, что не знают о ней.

[42] Для этого щелкните правой кнопкой мыши на существующем столбце и выберите команду Select Columns (Выбрать стсшбцы).

[43] Хотелось бы еще раз продемонстрировать, насколько удручающе обстоят дела. Откройте приложение Notepad.exe и посмотрите с помощью Диспетчера задач количество связанных с ним потоков. Выберите в меню File (Файл) приложения команду Open (Открыть), и как только откроется диалоговое окно File Open (Открытие файла), посмотрите на количество новых потоков. На моей машине результатом открытия этого окна стало создание 31 дополнительного потока! Аналогично обстоят дела с любым другим приложением, открывающим диалоговое окно открытия или сохранения файла. И большинство этих потоков не завершается даже после закрытия окна!

[44] Класс Thread также предлагает конструктор, принимающий делегат ThreadStart, который не имеет аргументов и не возвращает значений. Но лично я не рекомендую их использовать из-за многочисленных ограничений. Если метод вашего потока принимает класс Object и возвращает значение типа void, вызовите его при помощи выделенного потока или пула потока, как показано в главе 27.

[45] Можно также заметить, что поток находился в системе более 25 часов, но использовался менее чем одну секунду процессорного времени. То есть речь идет о непродуктивном расходов; ресурсов.

[46] Добавляемые к контексту логического вызова элементы должны быть сериализуемыми (см. главу 24). Копирование контекста исполнения, содержащего данные контекста логического вызова, крайне отрицательно сказывается на производительности, так как требует серилизации и десериализации всех элементов данных.

[47] Попытка отменить задание до начала его выполнения приводит к появлению исключения InvalidOperationException.

[48] Класс ParallelQuery<T> является производным от ParallelQuery.

[49] Поведение других объектов, производных от класса TaskScheduler, может отличаться от описываемого в данном разделе.

[50] Готовые IRP-пакеты извлекаются из пула по алгоритму «первым пришел — первым обслужен».

[51] Предполагается, что другие потоки в это время отсутствуют. Большую часть времени действительно так, ведь большинство компьютеров не задействует процессор на 100 %. Однако даже при полной загрузке процессора все будет работать описанным образом, если исполняемые потоки имеют низкие приоритеты. Наличие других потоков приводит к переключениям контекста. Это плохо с точки зрения производительности, но хорошо с точки зрения надежности. Напоминаю, что Windows выделяет на каждый процесс по крайней мере один поток и переключает контекст, гарантируя, что даже блокировка одного потока не остановит работу приложения.

[52] Разработчики, использующие версии Microsoft .NET Framework до 4.5, могут воспользоваться моим классом AsyncEnumerator (из библиотеки Power Threading — см. http:// Wintellect.com/) — его модель программирования достаточно похожа на модель .NET Framework 4.5. Собственно, успех класса AsnycEnumerator позволил мне помочь Microsoft в проектировании модели, рассматриваемой в этой главе. Ввиду их сходства адаптация кода, использующего класс AsyncEnumerator, для новой программной модели проходит тривиально.

[53] При попытке пометить ключевым словом async точку входа программы (Main) компилятор C# выдает сообщение об ошибке. Если размесить операторы await в методе Main, основной поток процесса вернет управление из Main сразу же после выполнения первого оператора await. А поскольку код, вызывающей Main, не может получить объект Task для отслеживания и ожидания завершения, процесс просто завершится (из-за возвращения управления из Main), а остальной код Main не будет выполнен. Компилятор C# считает подобную ситуацию ошибкой и принимает меры для ее предотвращения.

[54] Методы WinRT поддерживают те же соглашения об именах и возвращают интерфейс IAsyncInfo. К счастью, .NET Framework поддерживает методы расширения, которые преобразуют IAsyncInfo в Task. Дополнительная информация об использовании асинхронных WinRT API с асинхронными функциями приведена в главе 25.