Download - Async clinic by by Sergey Teplyakov
![Page 1: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/1.jpg)
Асинхронное программирование
Сергей Тепляков, Visual C# MVP.NET Architect at Luxoft
SergeyTeplyakov.blogspot.com
![Page 2: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/2.jpg)
Sync vs Async
SynchronousPerform something here and now.I’ll regain control to execute something else when it’s done.
AsynchronousInitiate something here and now.I’ll regain control to execute something else “immediately”.
![Page 3: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/3.jpg)
Эволюцияязыка C#
![Page 4: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/4.jpg)
Sync vs AsyncCaller Srv
Foo
42
Caller Srv
Operation finishedResult: 42
FooAsync
Operation Started
Bckgn
Starting background operation
Notifies
t
t
t0
Sync vs Async
![Page 5: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/5.jpg)
Sync vs Asyncvar 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 6: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/6.jpg)
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 7: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/7.jpg)
!Копайте в глубьВсе нетривиальные абстракции дырявыДжоэл Спольски «Закон дырявых абстракций»
Вы должны понимать как минимум на один уровень абстракции ниже того уровня, на котором вы кодируетеЛи Кэмпбел (Lee Campbell)
![Page 8: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/8.jpg)
Async/await – лишьвершина
![Page 9: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/9.jpg)
Async/Await Samplepublic async Task AsyncMethod(string url, string fileName){ var webRequest = WebRequest.Create(url); Task<WebResponse> tResp = webRequest.GetResponseAsync(); WebResponse response = await tResp;
var responseStream = response.GetResponseStream(); var tr = new StreamReader(responseStream); Task<string> tContent = tr.ReadToEndAsync(); string content = await tContent;
var file = File.OpenWrite(fileName); var streamWriter = new StreamWriter(file); Task writeResult = streamWriter.WriteAsync(content); await writeResult;
Console.WriteLine("AsyncMethod finished");}
![Page 10: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/10.jpg)
Async/Await SampleКод Потокvar webRequest = WebRequest.Create(url);Task<WebResponse> tResp = webRequest.GetResponseAsync();
Вызывающий поток
Await возвращает управление вызывающему кодуWebResponse response = await tResp;var responseStream = response.GetResponseStream(); var tr = new StreamReader(responseStream);Task<string> tContent = tr.ReadToEndAsync();
Поток 2
Await возвращает управление вызывающему кодуstring content = await tContent; var file = File.OpenWrite(fileName);var streamWriter = new StreamWriter(file);Task writeResult = streamWriter.WriteAsync(content);
Поток 3
Await возвращает управление вызывающему кодуawait writeResult;Console.WriteLine("AsyncMethod finished");
Поток 4
Метод завершен успешно
![Page 11: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/11.jpg)
Async vs. Taskspublic async Task SimpleAsync(string url){ var webRequest = WebRequest.Create(url); Task<WebResponse> tResp = webRequest.GetResponseAsync(); WebResponse response = await tResp; Console.WriteLine("Got the response");}
public Task AsyncMethodImpl(string url){ var webRequest = WebRequest.Create(url); Task<WebResponse> tResp = webRequest.GetResponseAsync(); return tResp.ContinueWith(t => { Console.WriteLine("Got the response"); }, TaskScheduler.FromCurrentSynchronizationContext());}
![Page 12: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/12.jpg)
Synchronization Context• Некоторые типы приложений налагают ограничения на
«потоковую» модель• Control.Invoke/BeginInvoke• Dispatcher.Invoke/BeginInvoke
• Контекст синхронизации «прячет» эти детали за абстрактным интерфейсом
• Контекст нужен для «маршалинга» управления из одного потока в другой (*)
• Контексты повсюду!
![Page 13: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/13.jpg)
?Зачеммнеэто Яжепрограммируюна C#
5.0!
![Page 14: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/14.jpg)
?Чтобудет в этомслучаеprivate async Task<int> Foo(){ buttonRun.Enabled = false; await LongRunningTask(); buttonRun.Enabled = true; return 42;}
private void btn_Click(object sender, EventArgs e) { label.Text = FooAsync().Result.ToString(); }
«Продолжение» должно вызываться в UI потоке
Ожидает завершения асинхронной операции
Захватываем Sync Context
Возвращает управление!
![Page 15: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/15.jpg)
“Sync over Async” + UI == Deadlock!
![Page 16: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/16.jpg)
Решениеprivate async Task<int> Foo(){ buttonRun.Enabled = false; await LongRunningTask(); buttonRun.Enabled = true; return 42;}
private async void buttonRun_Click(object sender, EventArgs e){ textBoxStatus.Text = ""; textBoxStatus.Text = (await Foo()).ToString();}
![Page 17: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/17.jpg)
Паттерныасинхронногопрограммирования• Asynchronous Programming Model (APM)
• BeginInvoke/EndInvoke• Event-Based Async Pattern (EAP)
• BackgroundWorker: RunWorkerAsync, RunWorkerCompleted• Bicycle –Async Pattern (BAP)
• Кастомные решения• Task-Based Async Pattern (TAP)
• Task<int> ReadAsync
![Page 18: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/18.jpg)
Exception Handling
Task.ResultTask.Wait
await task; FirstException
AggregateExceptionfails
fails
![Page 19: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/19.jpg)
Demo. Exception Handling
![Page 20: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/20.jpg)
?Гдевылетитошибкаvar ms = new MemoryStream();
// Здесь? Task<int> task = ms.ReadAsync(null, 0, 42);
// Или здесь? int result = task.Result;
• Является исключение «синхронным» или «асинхронным»?
![Page 21: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/21.jpg)
« » Наивная реализацияpublic static async Task<int> ReadAsync(byte[] buffer) { if (buffer == null) throw new ArgumentNullException("buffer");
// Реализация асинхронного чтения return 42; }
Результирующая задача перейдет в Faulted состояние!
• Синхронное исключение означает «баг» в вызывающем коде.
• «Поломанная» задача означает баг в реализации!
Зачем заморачиваться?
![Page 22: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/22.jpg)
Корректнаяреализация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 23: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/23.jpg)
Demo. Exception Handling
![Page 24: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/24.jpg)
Обработканесколькихисключений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 25: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/25.jpg)
Unobserved Exceptions• Событие TaskScheduler.UnobservedException• Генерируется финализатором• Не вызывается при обращении к
• Result• Exception • Вызове Wait
• Поведение зависит от версии .NET Framework• .NET 4.5 – «умалчивается» (*)• .NET 4.0 – «ломает» приложение
![Page 26: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/26.jpg)
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 27: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/27.jpg)
“Решение”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 28: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/28.jpg)
?Икакэтоделоловить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 29: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/29.jpg)
Асинхронныеметоды• Типы возвращаемого значения асинхронного метода:
• async void FooAasync() – Fire and Forget (*)• async Task FooAsync() – (void Foo())• async Task<T> FooAsync() – (T Foo())
![Page 30: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/30.jpg)
Demo. Async Void
![Page 31: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/31.jpg)
Async Guidelines• Async void – это операции вида “fire-and-forget”• Вызывающий код не может узнать о завершении
асинхронного метода• Вызывающий код не может обработать исключения
(вместо этого они попадут в цикл обработки UI сообщений)
• Используйте async void только для обработчиков событий самого высокого уровня.
• Используйте возвращаемые значения!• Осторожнее с асинхронными лямбда-выражениями!
![Page 32: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/32.jpg)
…Сколькожетут всего• Влияние 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 33: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/33.jpg)
Вот этогоненадо
- Как вы пишите софт?- Бац-бац и в продакшн (с).
- Как из синхронного приложения сделать асинхронное?- Async/await и готово!
![Page 34: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/34.jpg)
?Вопросы
![Page 35: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/35.jpg)
Спасибо за внимание
• Сергей Тепляков, Visual C# MVP• .NET Architect at Luxoft• [email protected]• http://sergeyteplyakov.blogspot.com/
![Page 36: Async clinic by by Sergey Teplyakov](https://reader036.vdocuments.mx/reader036/viewer/2022081414/54c2e5b74a7959896c8b45ae/html5/thumbnails/36.jpg)
Чтодумаетпоэтому поводу 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.