Дополнительные возможности AsyncEnumerator - Поддержка APM
ОГЛАВЛЕНИЕ
Поддержка APM
В моей предыдущей статье я объяснил, как вызов метода Execute AsyncEnumerator начинает исполнение кода итератора. Однако я также объяснил, что поток, вызывающий Execute, будет блокироваться до выхода из итератора или исполнения им оператора yield break.
Блокировка потока может повредить масштабируемости приложения и крайне нежелательна, особенно в серверных приложениях. Она также вредит скорости ответа при вызове потоком графического интерфейса пользователя, поскольку на исполнение итератора уходит неопределенный промежуток времени, и в течение этого времени приложение Windows® Forms или Windows Presentation Foundation (WPF) не будет реагировать на ввод. Вызывать Execute определено стоит только при написании тестового кода или экспериментах с методом итератора.
Для рабочего кода следует вызывать такие методы AsyncEnumerator, как BeginExecute и EndExecute. Внутренне, при вызове BeginExecute, объект AsyncEnumerator конструирует экземпляр класса AsyncResultNoResult, о котором я рассказывал в выпуске журнала MSDN® Magazine за март 2007 года (msdn.microsoft.com/magazine/cc163467). При вызове BeginExecute можно передать ссылку на ваш собственный метод AsyncCallback, и объект AsyncEnumerator вызовет этот метод, когда итератор завершит его исполнение. Затем этот метод должен вызвать метод EndExecute из AsyncEnumerator для получения результатов итератора. Ниже я покажу несколько примеров, в которых я пользуюсь преимуществами методов BeginExecute и EndExecute. Такой метод выглядит следующим образом:
public class AsyncEnumerator<TResult>: AsyncEnumerator {
public IAsyncResult BeginExecute(
IEnumerator<Int32> enumerator,
AsyncCallback callback, Object state);public void EndExecute(IAsyncResult result);
}
Также, поскольку AsyncEnumerator поддерживает APM, его можно интегрировать со всеми моделями приложений Microsoft .NET Framework, поскольку они уже поддерживают APM. Это значит, что AsyncEnumerator можно использовать с приложениями веб-форм ASP.NET, веб-службами XML ASP.NET, службами Windows Communication Foundation (WCF), приложениями Windows Forms, приложениями WPF, консольными приложениями, службами Windows и так далее.
Также стоит указать, что поскольку AsyncEnumerator поддерживает APM, его можно использовать внутри другого итератора для компоновки асинхронных операций. Например, можно создать итератор, который знает, как асинхронно выполнить запрос к базе данных и обработать его результат, когда тот появится. Я называю это подпрограммой-итератором. Затем внутри другого итератора можно инициализировать несколько запросов к базе данных, вызвав подпрограмму-итератор в цикле. Для каждой итерации цикла можно создать AsyncEnumerator и вызывать его метод BeginExecute, передавая ему имя подпрограммы-итератора и любые дополнительные аргументы, какие необходимо.
Обратите внимание, что эта модель дает важное преимущество: все подпрограммы-итераторы работают параллельно, не блокируя потоков (если лежащая в основе реализация APM не блокирует потоки, скажем в случае применения BeginXxx для постановки в очередь к пулу потоков ThreadPool делегата, ставящего блок до завершения какой-либо операции). Это позволяет создать простой итератор, включающий в себя одну асинхронную операцию и вызывающий ее изнутри других итераторов, сохраняя при этом масштабируемость и скорость ответа.