Его Высочество async

30
Его Высочество Async Сергей Тепляков, Visual C# MVP .NET Architect at Luxoft SergeyTeplyakov.blogspot.com

Upload: luxoft-training

Post on 26-Mar-2016

264 views

Category:

Documents


1 download

DESCRIPTION

Synk vs Asynk

TRANSCRIPT

Page 1: Его Высочество Async

Его Высочество Async

Сергей Тепляков, Visual C# MVP .NET Architect at Luxoft

SergeyTeplyakov.blogspot.com

Page 2: Его Высочество Async

Эволюция языка C#

Page 3: Его Высочество Async

Sync vs Async

Synchronous Perform something here and now.

I’ll regain control to execute something else

when it’s done.

Asynchronous

Page 4: Его Высочество Async

Sync vs Async var webRequest = WebRequest.Create(Url); using (var response = webRequest.GetResponse()) { using (var file = new FileStream(FileName, FileMode.OpenOrCreate)) { var length = response.ContentLength; var textWriter = new StreamWriter(file); textWriter.Write(length.ToString()); textWriter.Close(); } }

Page 5: Его Высочество Async

Sync vs Async (2) var webRequest = WebRequest.Create(Url); using (var response = await webRequest.GetResponseAsync()) { using (var file = new FileStream(FileName, FileMode.OpenOrCreate)) { var length = response.ContentLength; var textWriter = new StreamWriter(file); await textWriter.WriteAsync(length.ToString()); textWriter.Close(); } }

Page 6: Его Высочество Async

Если вы думаете, что асинхронное программирование стало проще!

Page 7: Его Высочество Async

Копайте в глубь! Все нетривиальные абстракции дырявы Джоэл Спольски «Закон дырявых абстракций»

Вы должны понимать как минимум на один уровень абстракции ниже того уровня, на котором вы кодируете Ли Кэмпбел (Lee Campbell)

Page 8: Его Высочество Async

Async/await – лишь вершина

Page 9: Его Высочество Async

Synchronization Context

• Некоторые типы приложений налагают ограничения на «потоковую» модель

• Control.Invoke/BeginInvoke

• Dispatcher.Invoke/BeginInvoke

• Контекст синхронизации «прячет» эти детали за абстрактным интерфейсом

• Контекст нужен для «маршалинга» управления из одного потока в другой (*)

• Контексты повсюду!

Page 10: Его Высочество Async

Зачем мне это? Я же программирую на C# 5.0!

Page 11: Его Высочество Async

Что будет в этом случае?

private async Task<int> FooAsync() { await Task.Delay(10); return 42; } private void btn_Click(object sender, EventArgs e) { label.Text = FooAsync().Result.ToString(); }

Ожидает освобождения UI потока

Ожидает завершения асинхронной операции

Захватываем Sync Context

Возвращает управление!

Page 12: Его Высочество Async

“Sync over Async” + UI == Deadlock!

Page 13: Его Высочество Async

Решение private async Task<int> FooAsync() { await Task.Delay(10); return 42; } private async void btn_Click(object sender, EventArgs e) { label.Text = (await FooAsync()).ToString(); }

Page 14: Его Высочество Async

Обработка нескольких исключений public static async Task FooAsync() { // t1 "падает" Task<int> t1 = Task<int>.Factory.StartNew(() => { throw new Exception("E1"); }); // t2 тоже "падает" Task<int> t2 = Task<int>.Factory.StartNew(() => { throw new Exception("E2"); }); int r1 = await t1; int r2 = await t2; }

Получим “E1”?

Получим “E2”?

Получим AggregateException?

UnobservedTaskException!

Page 15: Его Высочество Async

Unobserved Exceptions

• Событие TaskScheduler.UnobservedException

• Генерируется финализатором

• Не вызывается при обращении к

• Result

• Exception

• Вызове Wait

• Поведение зависит от версии .NET Framework

• .NET 4.5 – «умалчивается» (*)

• .NET 4.0 – «ломает» приложение

Page 16: Его Высочество Async

Await исключений public static async Task<int> SimpleAsync() { throw new CustomException(); } public static async void ConsumeSimpleAsync() { var task = SimpleAsync(); try { // "Разыменовывание" задачи приводит к // "разворачиванию" первого исключения! int result = await task; } catch (CustomException) { Console.WriteLine("Yahoo!!!"); } }

Page 17: Его Высочество Async

“Решение” public static async Task FooAsync() { // t1 "падает" Task<int> t1 = Task<int>.Factory.StartNew(() => { throw new Exception("E1"); }); // t2 тоже "падает" Task<int> t2 = Task<int>.Factory.StartNew(() => { throw new Exception("E2"); }); // "Наблюдаем" оба исключения var task = Task.WhenAll(t1, t2); await task.ContinueWith(_ => _.Result); int r1 = t1.Result; int r2 = t2.Result; }

«Объединяем» обе задачи

await task; пробросил бы лишь первое исключение! Явно генерируем AggregateException!!!!

Page 18: Его Высочество Async

И как это дело ловить? var task = Modified.FooAsync(); try { await task; } // Для случая более одного исключения catch (AggregateException e) { // "Выпрямляем" все исключения int count = e.Flatten().InnerExceptions.Count; Console.WriteLine( "Demo2.Modified.FooAsync failed with {0} exceptions", count); } // Для более простых случаев catch (CustomException e) { } catch (Exception e) {}

Page 19: Его Высочество Async

Где вылетит ошибка? var ms = new MemoryStream(); // Здесь? Task<int> task = ms.ReadAsync(null, 0, 42); // Или здесь? int result = task.Result;

• Является исключение «синхронным» или «асинхронным»?

Page 20: Его Высочество Async

«Наивная» реализация public static async Task<int> ReadAsync(byte[] buffer) { if (buffer == null) throw new ArgumentNullException("buffer"); // Реализация асинхронного чтения return 42; }

Результирующая задача перейдет в Faulted состояние!

• Синхронное исключение означает «баг» в вызывающем коде.

• «Поломанная» задача означает баг в реализации!

Зачем заморачиваться?

Page 21: Его Высочество Async

Корректная реализация

public static Task<int> ReadAsync(byte[] buffer) { if (buffer == null) throw new ArgumentNullException("buffer"); return ReadAsyncImpl(buffer); } private static async Task<int> ReadAsyncImpl(byte[] buffer) { // Реализация асинхронногочтения return 42; }

Синхронная проверка «предусловий»

Page 22: Его Высочество Async

Сколько же тут всего…

• Влияние TAP на дизайн приложения!

• Обработка исключений • Unobserved exceptions

• Bugs vs Task Faults

• Гранулярность асинхронных операций

• Testability

• Work stealing

• Async Programming Guidelines • Avoid “async void”

• Avoid async lambdas

• Consider performance impact

• Avoid “Sync over Async”

• Avoid “Async over Sync”

• Consider using ConfigureAwait

Page 23: Его Высочество Async

Вот этого не надо

- Как вы пишите софт? - Бац-бац и в продакшн (с).

- Как из синхронного приложения сделать асинхронное? - Async/await и готово!

Page 24: Его Высочество Async

Его высочество Async …

не так прост, как кажется;)

Page 25: Его Высочество Async

Вопросы?

Page 26: Его Высочество Async

Спасибо за внимание

• Сергей Тепляков, Visual C# MVP

• .NET Architect at Luxoft

[email protected]

• http://sergeyteplyakov.blogspot.com/

Page 27: Его Высочество Async

Что думает по этому поводу Eric Lippert? Q: C# 5.0 has new feature called async/await. Why should developers be excited about it? A: People like me, are excited about this feature because its a cooperative multitasking with coroutines implementing using continuation passing style.

Page 28: Его Высочество Async

Task vs Observables

Page 29: Его Высочество Async

TaskCompletionSource фасад к старому асинхронному

миру!

Page 30: Его Высочество Async

Пример

public Task<CustomData> GetCustomDataAsync() { var tcs = new TaskCompletionSource<CustomData>(); // Начинаем асинхронную операцию, и передаем // два специализированных делегата CustomProvider.ExecuteOperation(Operation.ReadCustomer, data => tcs.SetResult(data), e => tcs.SetException(e)); return tcs.Task; }

public class CustomProvider { public static void ExecuteOperation(Operation operationId, Action<CustomData> action, Action<Exception> func); }