Асинхронне виконання коду 2
Користувачі люблять програми, які працюють швидко. Користувачеві все одно, яке додаток перед ним - Windows Forms або Web додаток, йому навіть однаково яка швидкість його з'єднання з сервером, йому важливо одне, щоб відповідь на його дії прийшла якнайшвидше. І якщо користувач іноді робить невелику знижку на деяку загальмованість відгуків програми, коли використовує dial-up з'єднання, але маючи ADSL або виділену лінію, користувач буде незадоволений. Якщо ви пропустили перший абзац, то нічого не втратили, дорогий читачу, оскільки вам і без мене чудово відомо, що додаток повинен працювати так швидко на скільки це можливо в кожній конкретній ситуації, тобто код і використовувані технології повинні утримувати тонку рівновагу між часом розробки та швидкістю виконання (стійкість і безпека, зрозуміло, має бути максимальною незалежно від часу та суми, сплаченої за розробку). Час виконання Web-програми складається з кількох складових: часу пересилання даних між клієнтом та сервером, часу обробки вхідних даних середовищем та часу виконання програмного коду. Якщо на перші два фактори вплинути можна тільки зменшенням розміру даних, що пересилаються і оброблюються, то на останній фактор цілком залежить від розробника. Один із шляхів підвищення продуктивності полягає в розпаралелювання завдань. У цій статті буде розказано основи асинхронного виконання коду в ASP.NET 2.0.
Як це працює
Асинхронні операції та життєвий цикл сторінки
Порівняємо життєвий цикл синхронної та асинхронної ASP.NET сторінок (так ми називатимемо сторінки, що реалізують інтерфейси IHttpHandler та IHttpAsyncHandler,відповідно). Відмінності у життєвому циклі синхронної та асинхронної сторінок виявляються після виникнення події PreRender. У випадку асинхронної сторінки на етапі PreRender викликається асинхронний код, а нитка, призначена середовищем виконання для обробки запиту до сторінки, повертається в пул ниток. Після завершення асинхронної операції середовище виконання отримує з пула ниток нову нитку і передає їй керування. Ще раз слід зазначити, що у випадку асинхронної сторінки, призначена для виконання запиту нитка повертається в пул ниток і може обслуговувати інші запити, поки відбувається виконання асинхронного запиту.
| Синхронна сторінка |

Реалізація асинхронної сторінки
Все починається з встановлення атрибута Async директиви @ Page. Якщо цей атрибут встановлено, то клас сторінки, що динамічно генерується, буде реалізовувати інтерфейс IHttpAsyncHandler. Атрибут AsyncTimeout вказує максимальну кількість часу за секунди, відведене виконання асинхронних операцій.
Після того, як сторінка "готова" до використання асинхронних дзвінків, необхідно реалізувати код та зареєструвати його для асинхронного виконання. Тут програміст має кілька можливих варіантів.
1. Метод AddOnPreRenderCompleteAsync
Метод AddOnPreRenderCompleteAsync викликається в обробнику події Load сторінки і призначений для реєстрації двох обробників початку та кінця асинхронної обробки.
Метод BeginAsync викликається середовищем виконання ASP.NET після події PreRender і завдання цього в тому, щоб розпочати асинхронну операцію.
При цьому нитка, використана для обробки запиту, повертається в пул ниток. Після завершення асинхронної операції (приумови, що не відбувається тайм-аут) з пула ниток витягується нитка, викликається метод EndAsync, відбувається подія PreRenderComplete та продовжується обробка запиту.
Для того, щоб перевірити, що це відбувається саме так, до коду методів BeginAsync і EndAsync потрібно додати виклик Trace.Write() і включити трасування для сторінки (атрибут Trace директиви Page встановити в true, якщо хтось забув як це робиться).

2. Метод RegisterAsyncTask
Метод RegisterAsyncTask використовується, якщо необхідно провести більше однієї асинхронної операції. Більше того, RegisterAsyncTask дозволяє встановити обробник, який буде викликаний якщо асинхронна операція не вкладеться за часом у встановлений атрибутом AsyncTimeout час, а також дозволяє передати в делегат, що використовується для реалізації асинхронного виклику, відомості про стан і вказати, чи може завдання виконуватися паралельно з іншими поставленими у чергу асинхронними завданнями. Детальний опис класу PageAsyncTask можна переглянути в MSDN. У випадку, коли вищезазначене не потрібно, можна використовувати AddOnPreRenderCompleteAsync і уникнути написання зайвого коду.
3. Можливості проксі-класу Web-служби для асинхронного виклику Web-служби
Проксі-клас Web-служби дозволяє використовувати власну модель подій для асинхронного виклику. Наприклад, клас Web-служби, використаної у прикладі, надає такі методи та властивості.
Як видно з наведеного лістингу, клас Web-служби надає події Completed, які відповідають завершенню виконання запитів до Web-служби. А також методи Async, які ініціюють асинхронне виконання. Таким чином, асинхронний виклик до Web-служби може бути реалізований так, як це показано в наведеному нижче лістингу.
УМетоди Async класу Web-служби також мають додаткові переваги перед RegisterAsyncTask і AddOnPreRenderCompleteAsync, оскільки в обробнику події Completed доступні об'єкти контексту виконання.