Net framework 5, а также среды Visual Studio 2012 и C#


Преобразование асинхронной функции



Download 6,27 Mb.
Pdf ko'rish
bet592/658
Sana12.06.2023
Hajmi6,27 Mb.
#950840
1   ...   588   589   590   591   592   593   594   595   ...   658
Bog'liq
CLR via C Programmirovanie na platforme Microsoft NET Framework 4 5 na yazyke C

Преобразование асинхронной функции 
в конечный автомат
Работа с асинхронными функциями станет более эффективной, если вы будете по-
нимать суть преобразований кода, которые компилятор выполняет за вас. На мой 
взгляд, разобраться в происходящем проще всего на конкретном примере, поэтому 
мы начнем с определения нескольких простых типов и методов.
internal sealed class Type1 { } 
internal sealed class Type2 { } 
private static async Task Method1Async() { 
/* Асинхронная операция, возвращающая объект Type1 */

private static async Task Method2Async() {
/* Асинхронная операция, возвращающая объект Type2 */
}
Теперь я приведу асинхронную функцию, которая использует эти простые типы
и методы.
private static async Task MyMethodAsync(Int32 argument) { 
Int32 local = argument
try { 
Type1 result1 = await Method1Async(); 
for (Int32 x = 0; x < 3; x++) { 
Type2 result2 = await Method2Async(); 


catch (Exception) { 
Console.WriteLine("Catch"); 

finally { 
Console.WriteLine("Finally"); 

return "Done"; 
}


796
Глава.28 .Асинхронные.операции.ввода-вывода
Код 
MyMethodAsync
выглядит довольно запутанно, но он демонстрирует не-
сколько ключевых моментов. Во-первых, сама асинхронная функция возвращает 
Task
, но в теле кода возвращается 
String
. Во-вторых, в ней вызываются 
другие функции, которые выполняют асинхронные операции — одна автономно, 
другая в цикле 
for
. Наконец, также присутствует код обработки исключений. 
При компиляции 
MyMethodAsync
компилятор преобразует код метода в структуру 
конечного автомата с возможностью приостановки и продолжения выполнения.
Я взял приведенный код, откомпилировал его, а затем преобразовал IL-код 
обратно в исходный код C#. Далее я слегка упростил код и добавил подробные 
комментарии, чтобы вы поняли, что делает компилятор для работы асинхронных 
функций. Ниже приведен основной код, созданный в результате преобразования. 
Я показываю как преобразованный метод 
MyMethodAsync
, так и структуру конечного 
автомата, от которой он зависит.
// Атрибут AsyncStateMachine обозначает асинхронный метод
// (полезно для инструментов, использующих отражение);
// тип указывает, какая структура реализует конечный автомат.
[DebuggerStepThrough, AsyncStateMachine(typeof(StateMachine))] 
private static Task MyMethodAsync(Int32 argument) { 
// Создание экземпляра конечного автомата и его инициализация
StateMachine stateMachine = new StateMachine() { 
// Создание построителя, возвращающего Task.
// Конечный автомат обращается к построителю для назначения
// завершения задания или выдачи исключения.
m_builder = AsyncTaskMethodBuilder.Create(),
m_state = 1, // инициализация местонахождения
m_argument = argument // Копирование аргументов в поля конечного
}; // автомата
// Начало выполнения конечного автомата.
stateMachine.m_builder.Start(ref stateMachine); 
return stateMachine.m_builder.Task; // Возвращение задания конечного
} // автомата
// Структура конечного автомата
[CompilerGenerated, StructLayout(LayoutKind.Auto)] 
private struct StateMachine : IAsyncStateMachine { 
// Поля для построителя конечного автомата (Task) и его местонахождения
public AsyncTaskMethodBuilder m_builder; 
public Int32 m_state; 
// Аргумент и локальные переменные становятся полями: 
public Int32 m_argument, m_local, m_x; 
public Type1 m_resultType1; 
public Type2 m_resultType2; 
// Одно поле на каждый тип Awaiter.
// В любой момент времени важно только одно из этих полей. В нем
// хранится ссылка на последний выполненный экземпляр await,
// который завершается асинхронно: 


797
Преобразование.асинхронной.функции.в.конечный.автомат
private TaskAwaiter m_awaiterType1; 
private TaskAwaiter m_awaiterType2; 
// Сам конечный автомат
void IAsyncStateMachine.MoveNext() { 
String result = null; // Результат Task
// Вставленный компилятором блок try гарантирует
// завершение задания конечного автомата 
try { 
Boolean executeFinally = true; // Логический выход из блока 'try'
if (m_state == 1) { // Если метод конечного автомата
// выполняется впервые
m_local = m_argument; // Выполнить начало исходного метода

// Блок try из исходного кода
try { 
TaskAwaiter awaiterType1; 
TaskAwaiter awaiterType2; 
switch (m_state) { 
case 1: // Начало исполнения кода в 'try' 
// вызвать Method1Async и получить его объект ожидания
awaiterType1 = Method1Async().GetAwaiter(); 
if (!awaiterType1.IsCompleted) { 
m_state = 0; // 'Method1Async' 
// завершается асинхронно
m_awaiterType1 = awaiterType1; // Сохранить объект
// ожидания до возвращения
// Приказать объекту ожидания вызвать MoveNext
// после завершения операции
m_builder.AwaitUnsafeOnCompleted(ref awaiterType1, ref this); 
// Предыдущая строка вызывает метод OnCompleted
// объекта awaiterType1, что приводит к вызову
// ContinueWith(t => MoveNext()) для Task.
// При завершении Task ContinueWith вызывает MoveNext 
executeFinally = false; // Без логического выхода
// из блока 'try'
return; // Поток возвращает
} // управление вызывающей стороне
// 'Method1Async' завершается синхронно.
break; 
case 0: // 'Method1Async' завершается асинхронно
awaiterType1 = m_awaiterType1; // Восстановление последнего
break; // объекта ожидания
case 1: // 'Method2Async' завершается асинхронно
awaiterType2 = m_awaiterType2; // Восстановление последнего
goto ForLoopEpilog; // объекта ожидания

// После первого await сохраняем результат и запускаем цикл 'for'
продолжение



798
Download 6,27 Mb.

Do'stlaringiz bilan baham:
1   ...   588   589   590   591   592   593   594   595   ...   658




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish