Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
1
©LuxoftTraining2013
06 июля 2013
Тонкости асинхронного
программирования
Dev Labs
2
©LuxoftTraining2013
Эволюция языка C#
3
©LuxoftTraining2013
Sync vs Async
Synchronous
Perform something here and now.
I’ll regain control to execute something e...
4
©LuxoftTraining2013
Sync vs Async
Caller Srv
Foo
42
Caller Srv
Operation finished
Result: 42
FooAsync
Operation Started
...
5
©LuxoftTraining2013
Sync vs Async
var webRequest = WebRequest.Create(Url); 
using (var response = webRequest.GetResponse...
6
©LuxoftTraining2013
Sync vs Async (2)
var webRequest = WebRequest.Create(Url); 
using (var response = await webRequest.G...
7
©LuxoftTraining2013
Demo – sync 2 async
8
©LuxoftTraining2013
Если вы думаете, что
асинхронное программирование
стало проще!
9
©LuxoftTraining2013
Копайте в глубь!
Все нетривиальные абстракции дырявы
Джоэл Спольски «Закон дырявых абстракций»
Вы до...
10
©LuxoftTraining2013
Async/await – лишь вершина
11
©LuxoftTraining2013
Synchronization Context
 Некоторые типы приложений налагают
ограничения на «потоковую» модель
 Co...
12
©LuxoftTraining2013
Зачем мне это?
Я же программирую на C#
5.0!
13
©LuxoftTraining2013
private int GetAnswerToUltimateQuestion()
{
    buttonRun.Enabled = false;
    Thread.Sleep(1000);
...
14
©LuxoftTraining2013
private async Task<int> GetAnswerToUltimateQuestionAsync()
{
    buttonRun.Enabled = false;
    awa...
15
©LuxoftTraining2013
Другими словами…
private Task<int> GetAnswerToUltimateQuestionAsyncImpl()
{
    buttonRun.Enabled =...
17
©LuxoftTraining2013
“Sync over Async” + UI ==
Deadlock!
18
©LuxoftTraining2013
Решение
private async Task<int> GetAnswerAsync() 
{ 
    await Task.Delay(10); 
    return 42; 
} 
...
19
©LuxoftTraining2013
Где вылетит ошибка?
var ms = new MemoryStream();           
// Здесь? 
Task<int> task = ms.ReadAsyn...
20
©LuxoftTraining2013
«Наивная» реализация
public static async Task<int> ReadAsync(byte[] buffer) 
{ 
    if (buffer == n...
21
©LuxoftTraining2013
Корректная реализация
public static Task<int> ReadAsync(byte[] buffer) 
{ 
    if (buffer == null) ...
22
©LuxoftTraining2013
Await исключений
public static async Task<int> SimpleAsync() 
{ 
    throw new CustomException(); 
...
23
©LuxoftTraining2013
Обработка нескольких исключений
public static async Task FooAsync() 
{ 
    // t1 "падает" 
    Tas...
24
©LuxoftTraining2013
Unobserved Exceptions
 Событие TaskScheduler.UnobservedException
 Генерируется финализатором
 Не...
25
©LuxoftTraining2013
“Решение”
public static async Task FooAsync()
{ 
   // t1 "падает" 
   Task<int> t1 = Task<int>.Fac...
26
©LuxoftTraining2013
Структура исключений
AggregateException
task.ContinueWith()
AggregateException
Task.WhenAll(t1, t2)...
27
©LuxoftTraining2013
И как это дело ловить?
var task = Modified.FooAsync(); 
try 
{ 
    await task; 
} 
// Для случая б...
28
©LuxoftTraining2013
Асинхронные методы
 Типы возвращаемого значения асинхронного
метода:
 async void FooAasync() – Fi...
29
©LuxoftTraining2013
Где вылетит ошибка?
private static async void FooAsync()
{
throw new Exception("Ooops!");
}
It Dep...
30
©LuxoftTraining2013
Demo – async void exceptions
31
©LuxoftTraining2013
Задача: убедиться, что метод генерирует
исключение!
32
©LuxoftTraining2013
Naïve Approach
public static async Task FooAsync()
{
//throw new InvalidOperationException("Oops!")...
33
©LuxoftTraining2013
Рабочий вариант!
[Test]
public void Test_FooAsync_Throws()
{
// Sync over Asyc? ;)
ThrowsAsync<Inva...
34
©LuxoftTraining2013
Async Guidelines
 Async void – это операции вида “fire-and-forget”
 Вызывающий код не может узнат...
35
©LuxoftTraining2013
Сколько же тут всего…
 Влияние TAP на дизайн приложения!
 Обработка исключений
 Unobserved excep...
36
©LuxoftTraining2013
Вот этого не надо
- Как вы пишите софт?
- Бац-бац и в продакшн (с).
- Как из синхронного приложения...
37
©LuxoftTraining2013
Его высочество Async …
не так прост, как кажется;)
38
©LuxoftTraining2013
Что думает по этому поводу Eric Lippert?
Q: C# 5.0 has new feature called async/await. Why
should d...
39
©LuxoftTraining2013
Дополнительные ссылки
 pfxteam blog
 C# Async Tips and Tricks Part 2: Async Void
 MVP Summit pre...
40
©LuxoftTraining2013
!Благодарю за внимание
?Вопросы
41
©LuxoftTraining2013
IntHR
Luxtown
Информация об учебном центре
www.luxoft-training.ru/about
Расписание
www.luxoft-train...
Upcoming SlideShare
Loading in …5
×

Тонкости асинхронного программирования

1,745 views

Published on

  • Be the first to comment

Тонкости асинхронного программирования

  1. 1. 1 ©LuxoftTraining2013 06 июля 2013 Тонкости асинхронного программирования Dev Labs
  2. 2. 2 ©LuxoftTraining2013 Эволюция языка C#
  3. 3. 3 ©LuxoftTraining2013 Sync vs Async Synchronous Perform something here and now. I’ll regain control to execute something else when it’s done.
  4. 4. 4 ©LuxoftTraining2013 Sync vs Async Caller Srv Foo 42 Caller Srv Operation finished Result: 42 FooAsync Operation Started Bckgn Starting background operation Notifies t t t0 Sync vs Async
  5. 5. 5 ©LuxoftTraining2013 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();      }  }
  6. 6. 6 ©LuxoftTraining2013 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();      }  }
  7. 7. 7 ©LuxoftTraining2013 Demo – sync 2 async
  8. 8. 8 ©LuxoftTraining2013 Если вы думаете, что асинхронное программирование стало проще!
  9. 9. 9 ©LuxoftTraining2013 Копайте в глубь! Все нетривиальные абстракции дырявы Джоэл Спольски «Закон дырявых абстракций» Вы должны понимать как минимум на один уровень абстракции ниже того уровня, на котором вы кодируете Ли Кэмпбел (Lee Campbell)
  10. 10. 10 ©LuxoftTraining2013 Async/await – лишь вершина
  11. 11. 11 ©LuxoftTraining2013 Synchronization Context  Некоторые типы приложений налагают ограничения на «потоковую» модель  Control.Invoke/BeginInvoke  Dispatcher.Invoke/BeginInvoke  Контекст синхронизации «прячет» эти детали за абстрактным интерфейсом  Контекст нужен для «маршалинга» управления из одного потока в другой (*)  Контексты повсюду!
  12. 12. 12 ©LuxoftTraining2013 Зачем мне это? Я же программирую на C# 5.0!
  13. 13. 13 ©LuxoftTraining2013 private int GetAnswerToUltimateQuestion() {     buttonRun.Enabled = false;     Thread.Sleep(1000);     buttonRun.Enabled = true;     return 42; } private void buttonRun_Click_Sync(object sender, EventArgs e) {     int result = GetAnswerToUltimateQuestion();     textBoxStatus.Text = result.ToString(); } Sync Version Некоторая длительная операция!!
  14. 14. 14 ©LuxoftTraining2013 private async Task<int> GetAnswerToUltimateQuestionAsync() {     buttonRun.Enabled = false;     await Task.Delay(1000);     buttonRun.Enabled = true;     return 42; } private void buttonRun_Click_Async(object sender, EventArgs e) {     Task<int> result = GetAnswerToUltimateQuestionAsync();     textBoxStatus.Text = result.Result.ToString(); } Наивный подход… [Thread 2] Ожидает освобождения UI потока [Thread 1] Ожидает завершения асинхронной операции Захватываем Sync Context Возвращает управление!
  15. 15. 15 ©LuxoftTraining2013 Другими словами… private Task<int> GetAnswerToUltimateQuestionAsyncImpl() {     buttonRun.Enabled = false;     var task = LongRunningTask();     return task.ContinueWith(t =>         {             buttonRun.Enabled = true;             return 42;         }, TaskScheduler.FromCurrentSynchronizationContext()); } private void buttonRun_Click_Async_Impl(object sender, EventArgs e) {     Task<int> result = GetAnswerToUltimateQuestionAsyncImpl();     textBoxStatus.Text = result.Result.ToString(); }
  16. 16. 17 ©LuxoftTraining2013 “Sync over Async” + UI == Deadlock!
  17. 17. 18 ©LuxoftTraining2013 Решение private async Task<int> GetAnswerAsync()  {      await Task.Delay(10);      return 42;  }  private async void btn_Click(object sender,      EventArgs e)  {      label.Text = (await GetAnswerAsync()).ToString();  }
  18. 18. 19 ©LuxoftTraining2013 Где вылетит ошибка? var ms = new MemoryStream();            // Здесь?  Task<int> task = ms.ReadAsync(null, 0, 42);  // Или здесь?  int result = task.Result; • Является исключение «синхронным» или «асинхронным»?
  19. 19. 20 ©LuxoftTraining2013 «Наивная» реализация public static async Task<int> ReadAsync(byte[] buffer)  {      if (buffer == null)           throw new ArgumentNullException("buffer");      // Реализация асинхронного чтения      return 42;  } Результирующая задача перейдет в Faulted состояние! • Синхронное исключение означает «баг» в вызывающем коде. • «Поломанная» задача означает баг в реализации! Зачем заморачиваться?
  20. 20. 21 ©LuxoftTraining2013 Корректная реализация 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;  } Синхронная проверка «предусловий» Блоки итераторов ведут себя аналогично!
  21. 21. 22 ©LuxoftTraining2013 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!!!");      }  }
  22. 22. 23 ©LuxoftTraining2013 Обработка нескольких исключений 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!
  23. 23. 24 ©LuxoftTraining2013 Unobserved Exceptions  Событие TaskScheduler.UnobservedException  Генерируется финализатором  Не вызывается при обращении к  Result  Exception  Вызове Wait  Поведение зависит от версии .NET Framework  .NET 4.5 – «умалчивается» (*)  .NET 4.0 – «ломает» приложение
  24. 24. 25 ©LuxoftTraining2013 “Решение” 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!!!!
  25. 25. 26 ©LuxoftTraining2013 Структура исключений AggregateException task.ContinueWith() AggregateException Task.WhenAll(t1, t2); First Exception("E1") t1: Task Exception("E2") t2: Task First Second await вытянет первое исключение и получит AggregateException! Task.WhenAll(t1, t2); await  task.ContinueWith(_ => _.Result);
  26. 26. 27 ©LuxoftTraining2013 И как это дело ловить? 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) {}
  27. 27. 28 ©LuxoftTraining2013 Асинхронные методы  Типы возвращаемого значения асинхронного метода:  async void FooAasync() – Fire and Forget (*)  async Task FooAsync() – (void Foo())  async Task<T> FooAsync() – (T Foo())
  28. 28. 29 ©LuxoftTraining2013 Где вылетит ошибка? private static async void FooAsync() { throw new Exception("Ooops!"); } It Depends!
  29. 29. 30 ©LuxoftTraining2013 Demo – async void exceptions
  30. 30. 31 ©LuxoftTraining2013 Задача: убедиться, что метод генерирует исключение!
  31. 31. 32 ©LuxoftTraining2013 Naïve Approach public static async Task FooAsync() { //throw new InvalidOperationException("Oops!"); await Task.Delay(42); } [Test] public async void Test_FooAsync_Throws_1() { try { await FooAsync(); Assert.Fail("InvalidOperation was not thrown"); } catch (InvalidOperationException) { } } [Test] public async void Test_FooAsync_Throws_2() { Assert.Throws<InvalidOperationException>(async () => await FooAsync()); }
  32. 32. 33 ©LuxoftTraining2013 Рабочий вариант! [Test] public void Test_FooAsync_Throws() { // Sync over Asyc? ;) ThrowsAsync<InvalidOperationException>(FooAsync).Wait(); } public async static Task ThrowsAsync<T>(Func<Task> testCode) where T : Exception { try { await testCode(); // Если мы сюда попадем, то движок NUnit // бросит нужный тип исключения Assert.Throws<T>(() => { }); } catch (T) {} }
  33. 33. 34 ©LuxoftTraining2013 Async Guidelines  Async void – это операции вида “fire-and-forget”  Вызывающий код не может узнать о завершении асинхронного метода  Вызывающий код не может обработать исключения (вместо этого они попадут в цикл обработки UI сообщений или «уронят» приложение!)  Используйте async void только для обработчиков событий самого высокого уровня.  Используйте возвращаемые значения!  Осторожнее с асинхронными лямбда- выражениями!
  34. 34. 35 ©LuxoftTraining2013 Сколько же тут всего…  Влияние TAP на дизайн приложения!  Обработка исключений  Unobserved exceptions  Bugs vs Task Faults  Гранулярность асинхронных операций  Testability  Work stealing
  35. 35. 36 ©LuxoftTraining2013 Вот этого не надо - Как вы пишите софт? - Бац-бац и в продакшн (с). - Как из синхронного приложения сделать асинхронное? - Async/await и готово!
  36. 36. 37 ©LuxoftTraining2013 Его высочество Async … не так прост, как кажется;)
  37. 37. 38 ©LuxoftTraining2013 Что думает по этому поводу 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.
  38. 38. 39 ©LuxoftTraining2013 Дополнительные ссылки  pfxteam blog  C# Async Tips and Tricks Part 2: Async Void  MVP Summit presentation on async  Знакомство с асинхронными операциями в C# 5
  39. 39. 40 ©LuxoftTraining2013 !Благодарю за внимание ?Вопросы
  40. 40. 41 ©LuxoftTraining2013 IntHR Luxtown Информация об учебном центре www.luxoft-training.ru/about Расписание www.luxoft-training.ru/timetable Каталог курсов www.luxoft-training.ru/training/catalog_directions Контакты www.luxoft-training.ru/contacts www.facebook.com/TrainingCenterLuxoft Расписание, курсы, тренеры Условия обучения, логистика, контакты Luxtown Информационные ресурсы Luxoft Training

×