Рейтинговые книги
Читем онлайн Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 293 294 295 296 297 298 299 300 301 ... 642

Наряду с тем, что вам уже известно о многопоточности, такое заявление проливает свет на этот вопрос. Вспомните, что приложения с графическим пользовательским интерфейсом (Windows Forms, WPF) не разрешают прямой доступ к элементам управления из вторичных потоков, а требуют делегирования доступа. Вы уже видели объект Dispatcher в примере приложения WPF. В консольных приложениях, которые не используют WPF, это ограничение отсутствует. Речь идет о разных моделях синхронизации. С учетом всего сказанного давайте рассмотрим класс SynchronizationContext.

Класс SynchonizationContext является типом, предоставляющим виртуальный метод отправки, который принимает делегат, предназначенный для выполнения асинхронным образом. В результате инфраструктуры получают шаблон для надлежащей обработки асинхронных запросов (диспетчеризация для приложений WPF/Windows Forms, прямое выполнение для приложений без графического пользовательского интерфейса и т.д.). Он предлагает способ постановки в очередь единицы работы в контексте и подсчета асинхронных операций, ожидающих выполнения.

Как обсуждалось ранее, когда делегат помещается в очередь для асинхронного выполнения, он планируется к запуску в отдельном потоке, что обрабатывается средой .NET Core Runtime. Задача обычно решается с помощью управляемого пула потоков .NET Core Runtime, но может быть построена и специальная реализация.

Хотя такими связующими действиями можно управлять вручную в коде, шаблон async/await делает большую часть трудной работы. В случае применения await к асинхронному методу задействуются реализации SynchronizationContext и TaskScheduler целевой инфраструктуры. Например, если вы используете async/await в приложении WPF, то инфраструктура WPF обеспечит диспетчеризацию делегата и обратный вызов в конечном автомате при завершении ожидающей задачи, чтобы безопасным образом обновить элементы управления.

Роль метода ConfigureAwait()

Теперь, когда вы лучше понимаете роль класса SynchronizationContext, пришло время раскрыть роль метода ConfigureAwait(). По умолчанию применение await к объекту Task приводит к использованию контекста синхронизации. При разработке приложений с графическим пользовательским интерфейсом (Windows Forms, WPF) именно такое поведение является желательным. Однако в случае написания кода приложения без графического пользовательского интерфейса накладные расходы, связанные с постановкой в очередь исходного контекста, когда в этом нет нужды, потенциально могут вызвать проблемы с производительностью приложения.

Чтобы увидеть все в действии, модифицируйте операторы верхнего уровня, как показано ниже:

Console.WriteLine(" Fun With Async ===>");

// Console.WriteLine(DoWork());

string message = await DoWorkAsync();

Console.WriteLine(message);

string message1 = await DoWorkAsync().ConfigureAwait(false);

Console.WriteLine(message1);

В исходном блоке кода применяется класс SynchronizationContext, поставляемый инфраструктурой (в данном случае средой .NET Core Runtime), что эквивалентно вызову ConfigureAwait(true). Во втором примере текущий контекст и планировщик игнорируются.

(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})

Согласно рекомендациям команды создателей .NET Core при разработке прикладного кода (Windows Forms, WPF и т.д.) следует полагаться на стандартное поведение, а в случае написания неприкладного кода (скажем, библиотеки) использовать вызов ConfigureAwait(false). Одним исключением является инфраструктура ASP.NET Core (рассматриваемая в части IX), где специальная реализация SynchronizationContext не создается; таким образом, вызов ConfigureAwait(false) не дает преимущества при работе с другими инфраструктурами. 

Соглашения об именовании асинхронных методов

Конечно же, вы заметили, что мы изменили имя метода с DoWork() на DoWorkAsync(), но по какой причине? Давайте предположим, что новая версия метода по-прежнему называется DoWork(), но вызывающий код реализован так:

// Отсутствует ключевое слово await!

string message = DoWork();

Обратите внимание, что мы действительно пометили метод ключевым словом async, но не указали ключевое слово await при вызове DoWork(). Здесь мы получим ошибки на этапе компиляции, потому что возвращаемым значением DoWork() является объект Task, который мы пытаемся напрямую присвоить переменной типа string. Вспомните, что ключевое слово await отвечает за извлечение внутреннего возвращаемого значения, которое содержится в объекте Task. Поскольку await отсутствует, возникает несоответствие типов.

На заметку! Метод, поддерживающий await — это просто метод, который возвращает Task или Task<T>.

С учетом того, что методы, которые возвращают объекты Task, теперь могут вызываться в неблокирующей манере посредством конструкций async и await, в Microsoft рекомендуют (в качестве установившейся практики) снабжать имя любого метода, возвращающего Task, суффиксом Async. В таком случае разработчики, которым известно данное соглашение об именовании, получают визуальное напоминание о том, что ключевое слово await является обязательным, если они намерены вызывать метод внутри асинхронного контекста.

На заметку! Обработчики событий для элементов управления графического пользовательского интерфейса (вроде обработчика события Click кнопки), а также методы действий внутри приложений в стиле MVC, к которым применяются ключевые слова async и await, не следуют указанному соглашению об именовании.

Асинхронные методы, возвращающие void

В настоящий момент наш метод DoWorkAsync() возвращает объект Task, содержащий "реальные данные" для вызывающего кода, которые будут получены прозрачным образом через ключевое слово await. Однако что если требуется построить асинхронный метод, возвращающий void? Реализация зависит о того, нуждается метод в применении await или нет (как в сценариях "запустил и забыл").

1 ... 293 294 295 296 297 298 299 300 301 ... 642
На этой странице вы можете бесплатно читать книгу Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю бесплатно.
Похожие на Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю книги

Оставить комментарий