async/await:собираемграбли - jug ru...
TRANSCRIPT
![Page 1: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/1.jpg)
async/await: собираем грабли Андрей Часовских
Broadridge Financial Solu>ons
.NEXT 2014 Moscow
![Page 2: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/2.jpg)
Асинхронное программирование
• Управление получаем сразу после вызова операции • Об окончании операции нас уведомляет коллбэк • Преимущества
• Отзывчивость • Масштабируемость
2
![Page 3: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/3.jpg)
Асинхронное программирование в .NET
• Asynchronous Programming Model (BeginXxx/EndXxx) • Event-‐based Asynchronous Programming (XxxAsync(), XxxCompleted) • Task-‐based Asynchronous Programming (async/await, Task/Task<T>)
• Ссылка на документ в конце презентации
3
![Page 4: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/4.jpg)
4
![Page 5: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/5.jpg)
Асинхронность != многопоточность
5
![Page 6: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/6.jpg)
Синхронный ввод-‐вывод
var stream = new FileStream(…); int bytes = stream.Read(…);
WinAPI ReadFile(…)
Диспетчер ввода-‐вывода Блокирует
поток Очередь пакетов
6
![Page 7: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/7.jpg)
Сервер в вакууме
Синхронный ввод-‐вывод: пример
Жесткий диск
7
![Page 8: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/8.jpg)
Асинхронный ввод-‐вывод
var stream = new FileStream(…, FileOp>ons.Asynchronous); int bytes = await stream.ReadAsync(…);
WinAPI ReadFile(…)
Диспетчер ввода-‐вывода
Возвращает управление
Очередь пакетов
8
Overlapped
![Page 9: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/9.jpg)
Асинхронный ввод-‐вывод: пример
9
Сервер в вакууме
Жесткий диск
![Page 10: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/10.jpg)
• Ключевое слово async • Разрешает использовать await • «Передает» результат метода или исключение вверх по стеку • Для такого метода компилятор генерирует стейт-‐машину
• Ключевое слово await • Вставляет точку возможного прерывания/возобновления метода • Извлекает результат или исключение из таска
async/await
10
![Page 11: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/11.jpg)
Реализация async Task FooAsync() { M1(); await BarAsync(); M2(); } // примерный сгенерированный код Task FooAsync() { var sm = new FooAsyncStruct(); sm.this = this; sm.builder = AsyncTaskMethodBuilder.Create(); sm.state = -‐1; … sm.MoveNext(); return sm.builder.Task; } 11
struct FooAsyncStruct : IAsyncStateMachine { public AsyncTaskMethodBuilder builder; public SomeType this; public int state; … private void MoveNext() { try { switch (state) { … } } catch (Exception ex) { builder.SetException(ex); return; } builder.SetResult(); } }
![Page 12: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/12.jpg)
12
async Task FooAsync() { M1(); await BarAsync(); M2(); }
// примерный код того, что происходит внутри каждого состояния M1(); var task = BarAsync(); var awaiter = task.GetAwaiter(); Action postback = () => { awaiter.GetResult(); M2(); } if (awaiter.IsCompleted) { postback(); } else { var context = SynchronizationContext.Current; if (context == null) { context = new SynchronizationContext(); } var contextCopy = context.CreateCopy(); awaiter.OnCompleted(() => contextCopy.Post(postback, null)); }
Контекст пула потоков
Захват контекста Синхронное выполнение
![Page 13: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/13.jpg)
Заблуждения
• async методы выполняются в другом потоке • С помощью await метод выполняется в другом потоке
• await вообще не запускает методы • Продолжение метода выполняется в другом потоке
• Не всегда: ожидаемый объект уже завершен или однопоточный контекст не был захвачен
13
![Page 14: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/14.jpg)
«async/await позволяет использовать модель синхронного программирования для написания кода, выполняющего операции
ввода-‐вывода без блокировки потоков. И т.о. создавать более отзывчивое и масштабируемое
программное обеспечение.»
Джеффри Рихтер
14
![Page 15: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/15.jpg)
async void
• Исключения выбрасываются в вызывающий контекст • Могут завершить процесс
• Не узнаем об окончании операции • Только для обработчиков событий и подобных штук
15
![Page 16: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/16.jpg)
Асинхронные лямбды
• Это Ac>on или Func<Task>? • Ac>on == async void • Проверять тип делегата! Task t = null; SomeMethod(() => t = FooAsync()); await t;
16
![Page 17: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/17.jpg)
Таск, которого не ждут
• Не узнаем об исключениях или узнаем слишком поздно • Могут завершить процесс • TaskScheduler.UnobservedTaskExcep>on
• Не узнаем об окончании операции
17
![Page 18: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/18.jpg)
Блокировка таска
• Блокируем текущий поток • Возможен дедлок
18
![Page 19: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/19.jpg)
Используйте Task.ConfigureAwait(false)
• Не захватываем текущий контекст • Минимизируем переключения между потоками
• Для библиотечных вызовов • Захват контекста – для вызовов верхнего уровня
19
![Page 20: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/20.jpg)
Async all the way
• Нежелательно смешивать синхронный и асинхронный код • async/await стремится распространяться по коду • Избавляемся от простых ошибок
20
![Page 21: async/await:собираемграбли - JUG Ru Grouppublic.jugru.org/dotnext/2014/moscow/chasovskikh.pdf• Ключевое’слово’async’ • Разрешает’использовать’await](https://reader036.vdocument.in/reader036/viewer/2022070107/6022c798621c065d213a848a/html5/thumbnails/21.jpg)
Спасибо!
• Pfx Team h�p://blogs.msdn.com/b/pfxteam/ • Stephen Cleary h�p://blog.stephencleary.com/ • Lucian Wischik h�p://blogs.msdn.com/lucian • TAP h�p://aka.ms/tap h�p://andreycha.info h�p://github.com/andreycha/DotNext2014Moscow
21