Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Асинхронный вызов методов






Платформа.NET содержит средства для поддержки асинхронного вызова методов. При асинхронном вызове поток выполнения разделяется на две части: в одной выполняется метод, а в другой – процесс программы. Асинхронный вызов служит альтернативой использованию многопоточности явным образом.

Асинхронный вызов всегда выполняется посредством объекта некоторого делегата. Любой такой объект содержит два специальных метода для асинхронных вызовов – BeginInvoke() и EndInvoke(). Эти методы генерируются во время выполнения программы, так как их сигнатура зависит от делегата. Внимание: объект группового делегата нельзя вызвать асинхронно.

Метод BeginInvoke() обеспечивает асинхронный запуск. Кроме параметров, указанных при описании делегата, метод BeginInvoke() имеет два дополнительных параметра. Первый дополнительный параметр указывает на функцию завершения, выполняемую после окончания асинхронного метода. Второй дополнительный параметр – это объект, при помощи которого функции завершения может быть передана некоторая информация. Метод BeginInvoke() возвращает объект, реализующий интерфейс IAsyncResult. При помощи этого объекта становится возможным различать асинхронные вызовы одного и того же метода.

Приведём описание интерфейса IAsyncResult:

interface IAsyncResult

{

object AsyncState{ get; }

WaitHandle AsyncWaitHandle{ get; }

bool CompletedSynchronously{ get; }

bool IsCompleted{ get; }

}

Поле IsCompleted позволяет узнать, завершилась ли работа асинхронного метода. В поле AsyncWaitHandle хранится объект типа WaitHandle. Программист может вызывать методы объекта WaitHandle для контроля над потоком выполнения асинхронного метода. Объект AsyncState хранит последний аргумент, указанный при вызове BeginInvoke().

Делегат для функции завершения описан следующим образом:

public delegate void AsyncCallback(IAsyncResult ar);

Как видим, функции завершения передаётся единственный аргумент – объект, реализующий интерфейс IAsyncResult.

Рассмотрим пример асинхронного вызова метода, который вычисляет и печатает факториал целого числа. Ни функции завершения, ни возвращаемое методом BeginInvoke() значение не используются. Подобный подход при работе с асинхронными методами называется «выстрелил и забыл» (fire and forget).

// создадим лямбду, чтобы вычислять факториал

Func< uint, BigInteger> factorial = null;

factorial = n => (n == 0)? 1: n * factorial(n - 1);

 

// создадим лямбду, чтобы печатать факториал

Action< uint> print = n => Console.WriteLine(factorial(n));

 

// запустим метод асинхронно, игнорируя дополнительные параметры

print.BeginInvoke(8000, null, null);

 

// эмулируем работу (факториал увидим где-то на третьей итерации)

for (int i = 1; i < 10; i++)

{

Console.Write(" Do some work...");

Thread.Sleep(3000);

}

Модифицируем предыдущий пример. Будем передавать в BeginInvoke() функцию завершения и дополнительный аргумент.

// объект print не изменился

// функция завершения будет выводить время выполнения метода

AsyncCallback timer = ar =>

{

var dt = (DateTime) ar.AsyncState;

Console.WriteLine(DateTime.Now - dt);

};

 

print.BeginInvoke(8000, timer, DateTime.Now);

print.BeginInvoke(1000, timer, DateTime.Now);

В разобранных примерах использовались асинхронные методы, которые не возвращают значения. В приложении может возникнуть необходимость в асинхронных методах-функциях. Для получения результата работы асинхронной функции предназначен метод EndInvoke(). Параметры EndInvoke() определяются на основе параметров метода, инкапсулированного делегатом. Во-первых, EndInvoke() является функцией, тип которой совпадает с типом инкапсулируемого метода. Во-вторых, метод EndInvoke() содержит все out и ref параметры делегата, а последний параметр имеет тип IAsyncResult. При вызове метода EndInvoke() основной поток выполнения приостанавливается до завершения работы соответствующего асинхронного метода.

Используем метод EndInvoke() при вычислении и печати факториала:

// объект factorial определён в первом примере

// так как отслеживаем окончание работы методов,

// сохраняем результат вызова BeginInvoke()

IAsyncResult ar1 = factorial.BeginInvoke(8000, null, null);

IAsyncResult ar2 = factorial.BeginInvoke(1000, null, null);

Thread.Sleep(2000);

 

// получаем результат второго вызова и печатаем его

BigInteger res1 = factorial.EndInvoke(ar2);

Console.WriteLine(res1);

 

// получаем и печатаем результат первого вызова

BigInteger res2 = factorial.EndInvoke(ar1);

Console.WriteLine(res2);

В заключение заметим, что технически асинхронный вызов методов реализуется средой исполнения при помощи пула потоков.


 

Литература

1. Албахари, Дж. C# 3.0. Справочник: Пер. с англ. / Дж. Албахари, Б. Албахари. – 3-е изд. – Спб.: БХВ-Петербург, 2009. – 944 с.: ил.

2. Нэш, Т. C# 2010: ускоренный курс для профессионалов / Т. Нэш. – М.: Издательский дом «Вильямс», 2010. – 592 с.

3. Троелсен, Э. Язык программирования C# 2010 и платформа.NET 4.0 / Э. Троелсен. – 5-е изд. – М.: ООО «И.Д. Вильямс», 2011. – 1392 с.: ил.

4. Рихтер, Дж. CLR via C#. Программирование на платформе Microsoft.NET Framework 4.0 на языке C# / Дж. Рихтер. – 3-е изд. – Спб.: Питер, 2012. – 928 с.: ил.

5. Фримен, А. LINQ: язык интегрированных запросов в C# 2010 для профессионалов / А. Фримен, Дж. С. Раттц-мл. – М.: Издательский дом «Вильямс», 2011. – 656 с.

6. Хейлсберг, А. Язык программирования C#. Классика Computers Science. / А. Хейлсберг, М. Торгерсен, С. Вилтамут, П. Голд. – 4-е изд. – Спб.: Питер, 2012. – 784 с.: ил.

7. Цвалина, К. Инфраструктура программных проектов: соглашения, идиомы и шаблоны для многократно используемых библиотек.NET.: Пер. с англ. / К. Цвалина. – М.: ООО «И.Д. Вильямс», 2011. – 416 с.: ил.


[1] Некоторые символы Unicode представлены двумя 16-битными «суррогатными» символами.

[2] Подробнее см. https://ru.wikipedia.org/wiki/Регулярные_выражения.

[3] Классы CultureInfo, NumberFormatInfo, DateTimeFormatInfo определены в пространстве имён System.Globalization.

[4] Тип string не перегружает операции сравнения, так как результат может измениться в зависимости от текущих региональных стандартов.

[5] Компилятор C# генерирует код, принудительно запускающий сборку мусора при окончании работы программы.

[6] Если бы использовалось foreach (var s in shop), то типом s был бы object.

[7] В пространстве имён System.Collections имеется слаботипизированный аналог класса List< T> – класс ArrayList.

[8] В пространстве имён System.Collections имеются слаботипизированные аналоги классов Queue< T> и Stack< T> – классы Queue и Stack.

[9] В пространстве имён System.Collections имеется слаботипизированный аналог класса Dictionary< TKey, TValue> – класс Hashtable.

[10] В пространстве имён System.Collections имеется слаботипизированный аналог класса Collection< T> – класс CollectionBase.

[11] Для использования System.Linq необходимо подключить сборку System.Core.dll.

[12] Все операторы LINQ имеют модификаторы public static. Для краткости эти модификаторы не указываются.

[13] Заметим, что класс FileStream уже обладает некоторой поддержкой буферизации.

[14] Запись + XName name означает наличие перегруженной версии метода, принимающей параметр name типа XName.

[15] Запись + params означает наличие перегруженной версии, принимающей параметр типа params object[].

[16] У класса XmlReader имеются также специфичные методы чтения конкретного содержимого XML-документа (например, ReadContentAsInt(), ReadAttributeValue()).

[17] Подробно о синтаксисе применения атрибутов и операторе typeof рассказывается далее.

[18] Класс StreamingContext описывает контекст потока сериализации. Основным свойством класса является State, принимающее значения из перечисления StreamingContextStates.

[19] Атрибуты размещены в пространстве имён System.Runtime.Serialization и одноимённой сборке.

[20] Visual Studio не позволяет работать с многофайловыми сборками, поэтому файлы примера нужно компилировать, используя компилятор командной строки csc.exe.

[21] Технология зондирования (probing) позволяет размещать зависимые сборки в подкаталогах.

[22] В случае веб-приложения файл конфигурации всегда называется web.config.

[23] В веб-приложениях используется System.Web.Configuration.WebConfigurationManager.

[24] Любой созданный поток резервирует примерно один мегабайт памяти под свои нужды.

[25] Прекращение работы фонового потока не гарантируется выполнение его блоков finally.

[26] Оба метода – Suspend() и Resume() – помечены как устаревшие. Использовать их не рекомендуется.

[27] public delegate void WaitCallback(object state);






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.