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

Post on 26-Mar-2016

264 Views

Category:

Documents

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

Synk vs Asynk

TRANSCRIPT

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

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

SergeyTeplyakov.blogspot.com

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

Sync vs Async

Synchronous Perform something here and now.

I’ll regain control to execute something else

when it’s done.

Asynchronous

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(); } }

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(); } }

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

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

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

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

Synchronization Context

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

• Control.Invoke/BeginInvoke

• Dispatcher.Invoke/BeginInvoke

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

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

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

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

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

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

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

“Sync over Async” + UI == Deadlock!

Решение 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(); }

Обработка нескольких исключений 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!

Unobserved Exceptions

• Событие TaskScheduler.UnobservedException

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

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

• Result

• Exception

• Вызове Wait

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

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

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

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!!!"); } }

“Решение” 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!!!!

И как это дело ловить? 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) {}

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

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

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

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

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

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

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

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

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; }

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

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

• Влияние 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

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

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

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

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

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

Вопросы?

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

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

• .NET Architect at Luxoft

• Sergey.Teplyakov@gmail.com

• http://sergeyteplyakov.blogspot.com/

Что думает по этому поводу 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.

Task vs Observables

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

миру!

Пример

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); }

top related