async clinic by by sergey teplyakov

36
Асинхронное программировани е Сергей Тепляков, Visual C# MVP .NET Architect at Luxoft SergeyTeplyakov.blogspot.com

Upload: alex-tumanoff

Post on 24-Jan-2015

3.446 views

Category:

Documents


6 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Async clinic by by Sergey Teplyakov

Асинхронное программирование

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

SergeyTeplyakov.blogspot.com

Page 2: Async clinic by by Sergey Teplyakov

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

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

Page 4: Async clinic by by Sergey Teplyakov

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

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

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

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

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

Page 8: Async clinic by by Sergey Teplyakov

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

Page 9: Async clinic by by Sergey Teplyakov

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

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

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

Synchronization Context• Некоторые типы приложений налагают ограничения на

«потоковую» модель• Control.Invoke/BeginInvoke• Dispatcher.Invoke/BeginInvoke

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

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

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

Page 13: Async clinic by by Sergey Teplyakov

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

5.0!

Page 14: Async clinic by by Sergey Teplyakov

?Чтобудет в этомслучае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

“Sync over Async” + UI == Deadlock!

Page 16: Async clinic by by Sergey Teplyakov

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

Паттерныасинхронногопрограммирования• 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

Exception Handling

Task.ResultTask.Wait

await task; FirstException

AggregateExceptionfails

fails

Page 19: Async clinic by by Sergey Teplyakov

Demo. Exception Handling

Page 20: Async clinic by by Sergey Teplyakov

?Гдевылетитошибкаvar ms = new MemoryStream();           

// Здесь? Task<int> task = ms.ReadAsync(null, 0, 42);

// Или здесь? int result = task.Result;

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

Page 21: Async clinic by by Sergey Teplyakov

« » Наивная реализация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

Корректнаяреализация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

Demo. Exception Handling

Page 24: Async clinic by by Sergey Teplyakov

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

Unobserved Exceptions• Событие TaskScheduler.UnobservedException• Генерируется финализатором• Не вызывается при обращении к

• Result• Exception • Вызове Wait

• Поведение зависит от версии .NET Framework• .NET 4.5 – «умалчивается» (*)• .NET 4.0 – «ломает» приложение

Page 26: Async clinic by by Sergey Teplyakov

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

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

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

Асинхронныеметоды• Типы возвращаемого значения асинхронного метода:

• 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

Demo. Async Void

Page 31: Async clinic by by Sergey Teplyakov

Async Guidelines• Async void – это операции вида “fire-and-forget”• Вызывающий код не может узнать о завершении

асинхронного метода• Вызывающий код не может обработать исключения

(вместо этого они попадут в цикл обработки UI сообщений)

• Используйте async void только для обработчиков событий самого высокого уровня.

• Используйте возвращаемые значения!• Осторожнее с асинхронными лямбда-выражениями!

Page 32: Async clinic by by Sergey Teplyakov

…Сколькожетут всего• Влияние 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

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

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

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

Page 34: Async clinic by by Sergey Teplyakov

?Вопросы

Page 35: Async clinic by by Sergey Teplyakov

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

• Сергей Тепляков, Visual C# MVP• .NET Architect at Luxoft• [email protected]• http://sergeyteplyakov.blogspot.com/

Page 36: Async clinic by by Sergey Teplyakov

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