2. О Вашем инструкторе
Сергей Тепляков
Visual C# MVP, RSDN Team member
Sergey.Teplyakov@gmail.com
SergeyTeplyakov.blogspot.com
1-2
3. Цели курса…
Слушатели изучат:
Достоинства и недостатки
синхронного программирования
Существующие паттерны
асинхронного программирования на
платформе .Net
Использование библиотеки
PowerThreading
Использование библиотеки TPL
Новые возможности C# 5
1-3
5. Roadmap
Модель синхронного
программирования
Паттерны асинхронного
программирования на платформе .Net
Недостатки существующих моделей
Библиотека PowerThreading
Библиотека TPL
C# 5.0: async и await
1-5
6. Недостатки синхронного
программирования
Плохая масштабируемость
Блокирование пользовательского
интерфейса
Низкая эффективность операций
ввода/вывода
Невозможность использования в
некоторых контекстах (например, с
JavaScript и Silverlight)
8. Плохая масштабируемость
Неэффективное использование
мощностей современных многоядерных
процессоров для CPU-Bound операций
Неэффективное выполнение IO-Bound
операций даже для одноядерных
процессоров
10. Блокировка пользовательского
интерфейса
// Обработчик кнопки получения данных от веб-страниц
private void receiveDataButton_Click(object sender, EventArgs e)
{
Stopwatch sw = Stopwatch.StartNew(); // 1
_summaryContentLength = 0; // 2
foreach (var url in urls)
{
// GetResponse возвращает результат синхронно
using (WebResponse webResponse = GetResponse(url)) // 3
{
ProcessResponse(webResponse); // 4
executionTimeTextBox.Text = sw.ElapsedMilliseconds.ToString();
}
}
}
11. А ведь это и не всегда
возможно!
Некоторые среды, такие как Silverlight и
JavaScript не поддерживают синхронные
операции
12. Рассматриваемые темы
Модель синхронного программирования
Паттерны асинхронного
программирования на платформе
.Net
Недостатки существующих моделей
Библиотека PowerThreading
Библиотека TPL
C# 5.0: async и await
14. Classical Async Pattern
Структура паттерна:
// Синхронный метод
public <return> Operation(<parameters>, <out params> )
// Методы классического асинхронного паттерна
public IAsyncResult BeginOperation(<parameters>, AsyncCallback callback,
object state)
public <return> EndOperation(IAsyncResult asyncResult, <out paramss>)
Пример:
public WebResponse GetWebResponse(string url, out TimeSpan duration);
public IAsyncResult BeginGetWebResponse(string ulr, object state);
public WebResponse EndGetWebResponse(IAsyncResult ar, out TimeSpan duration);
15. Classical Async Pattern
Метод BeginXXX инициирует асинхронную
операцию
Метод BeginXXX возвращает IAsyncResult,
который является маркером асинхронной
операции
AsyncCallback представляет собой
функцию, которая будет вызвана при
завершении операции
State представляет собой любой
пользовательский объект
16. Classical Async Pattern
Все by-value и by-ref параметры
синхронного метода становятся by-value
параметрами BeginXXX метода
Тип возвращаемого значения синхронного
метода совпадает с типом возвращаемого
значения EndXXX метода
ref и out параметры синхронного метода
добавляются в EndXXX метод
Исключения, генерируемые синхронным
методом, генерируются методом EndXXX
17. Примеры Classical Async
Pattern
Класс System.IO.Stream
public int Read(byte[] buffer, int offset, int count)
public IAsyncResult BeginRead(byte[] buffer, int offset, int count,
AsyncCallback callback, object state)
public int EndRead(IAsyncResult asyncResult)
Класс System.Net.WebRequest
public WebResponse GetWebResponse();
public IAsyncResult BeginGetWebResponse(AsyncCallback callback, object state);
public WebResponse EndGetResponse(IAsyncResult asyncResult);
18. Асинхронное выполнение
sd ClassicAsync
Form Client HttpWebRequest IO completion
webRequest1.BeginGetResponse()
webRequest2.BeginGetResponse()
webRequest2.ProcessResponse()
ProcessResponse()
UpdateUIElements()
webRequest1.ProcessResponse()
ProcessResponse()
UpdateUIElements()
19. Classical Async Pattern
В обработчике UI события:
Проинициализировать дополнительные поля (теперь без них
не обойтись)
Сделать неактивной кнопку
В цикле начать все операции асинхронно (вызывать метод
BeginGetResponse)
20. Classical Async Pattern
В обработчике завершения асинхронной
операции:
Получить WebResponse (вызывать метод EndGetReponse)
Обработать ответ, не забывая, что обработка происходит не
в потоке UI
Понять, что все асинхронные операции завершены (??)
(посчитать количество завершенных операций)
Сделать активной кнопку, если все операции таки
завершены
Если перед началом выполнения асинхронных операций
были выделены ресурсы, то освободить их вручную
21. Разница синхронного и
асинхронного вариантов для
трех веб-узлов
Среднее выполнение синхронного
варианта: 520мс
Среднее выполнение асинхронного
варианта: 280 мс
Количество строк кода в синхронном
решении: 20
Количество строк кода в асинхронном
решении: 78
23. Event-Based Async Pattern
class Class Model
AsyncCompletedEv entArgs
Находится в пространстве
+ Canceled: bool имен: System.ComponentModel Событие MethodCompleted
+ Error: Exception вызывается как при успешном,
+ UserState: object так и при неудачном завершении
метода.
Метод CancelMethod и событие
ProgressChanged являются
опциональными.
MethodCompletedEv entArgs
SomeType
Uses
+ Arg1: int
+ event MethodCompleted
+ Arg2: string
+ event ProgressChanged
+ Result: MethodResult
+ CancelMethod() : void
Uses
+ MethodAsync(string, int) : void
MethodResult
24. Event-Based Async Pattern
MethodAsync инициирует асинхронную
операцию
Есть только одно событие
MethodCompleted, EventArgs которого
содержат Result, Error, IsCanceled
Возможна, но не обязательна,
поддержка отмены и прогресса
выполнения
25. Event-Based Async Pattern
By-value и ref параметры синхронного
метода являются входными
параметрами метода MethodAsync
Ref и out-параметры становятся
readonly полями
MethodCompletedEventArgs
Событие MethodCompleted
вызывается в «правильном»
потоке (в потоке UI для WinForms
или WPF)
26. Event-Based Async Pattern
// Функция обработки принятых данных
private void receiveDataButton_Click(object sender, EventArgs e)
{
// Подготовка операции (отключение кнопки «Принять»,
// инициализация счетчиков и т.д.
foreach (var url in urls)
{
var webClient = new WebClient();
webClient.DownloadDataAsync(new Uri(url));
webClient.DownloadDataCompleted +=
(s, ev) =>
{
// Для обработки ошибки в этом случае нужно
// обратиться к ствойству ev.Error.
// Обработка результатов
};
}
}
27. Да как же между ними
выбрать?
Классический паттерн более
низкоуровневый и более гибкий
Event-Based паттерн более простой в
применении, в частности с UI
дизайнерами
Классический паттерн – для кода
общего назначения, Event-Based – для
компонентов
Не применяйте оба паттерна для одного
класса
28. Рассматриваемые темы
Модель синхронного программирования
Паттерны асинхронного
программирования на платформе .Net
Недостатки существующих
моделей
Библиотека PowerThreading
Библиотека TPL
C# 5.0: async и await
29. Недостатки моделей
асинхронного программирования
Непонятный поток исполнения (Control
Flow)
Сложность чтения кода и его
сопровождения
Сложность обработки ошибок
Невозможность использования
привычных языковых конструкций
(using, try/finally etc)
30. Рассматриваемые темы
Модель синхронного программирования
Паттерны асинхронного
программирования на платформе .Net
Недостатки существующих моделей
Библиотека PowerThreading
Библиотека TPL
C# 5.0: async и await
31. PowerThreading Library
Разработана Джеффри Рихтер и
компанией Wintellect
Содержит класс AsyncEnumerator для
упрощения работы с асинхронными
операциями
Содержит вспомогательные классы для
работы с многопоточностью (ResourceLock,
ReaderWriterGate etc)
Другие вспомогательные классы (Disposer,
Exception<T>, Singleton etc)
32. Класс AsyncEnumerator.
Основные концепции
Поддерживает гибкое управление
асинхронными операциями (отмену,
таймауты и т.п.)
Использует преимущество блока
итераторов (Iterator block) для
упрощения потока исполнения
Использует SynchronizationContext для
маршалинга потока выполнения в поток
UI
33. Класс AsyncEnumerator.
Простой пример
static IEnumerator<int> WorkerMethod()
{
// Инициируем n асинхронных операций,
// вызываем BeginRead, BeginGetWebResponse, BeginExecuteCommand etc
// "возвращаем" n, что говорит AsyncEnumerator-у
// о количестве запущенных асинхронных операций
yield return n;
// класс AsyncEnumerator вызовет в следующий раз
// метод MoveNext нашего енумератора (и мы здесь получим управление)
// только после завершения указанного количества асинхронных операций.
// Причем, если экземпляр класса AsyncEnumerator-а создавался
// с контекстом синхронизации (например, он создавался в потоке UI)
// то метод MoveNext будет вызван в потоке UI!
// Начинаем еще несколько асинхронных операций (например, k)
yield return k;
}
// Создаем экземпляр енумератора
AsyncEnumerator ae = new AsyncEnumerator();
// Запускаем асинхронные операции, всю грязную работу
// берет на себя AsyncEnumerator
ae.BeginExecute(WorkerMethod(), ae.EndExecute);
34. Отступление от темы. Блоки
итераторов
static IEnumerator<int> GetNumbers()
{
string padding = "tt";
Console.WriteLine(padding + "Первая строка метода GetNumbers()");
Console.WriteLine(padding + "Сразу перед yield return 7");
yield return 7;
Console.WriteLine(padding + "Сразу после yield return 7");
Console.WriteLine(padding + "Сразу перед yield return 42");
yield return 42;
Console.WriteLine(padding + "Сразу после yield return 42");
}
40. AsyncEnumerator
sd AsyncEnumerator
AsyncEnumerator WorkerMethod WebRequest IO Completion
calling to MoveNext()
webRequest1.BeginGetResponse()
Первый вызов MoveNext
енумератора
инициирует
ас инхронные операции. webRequest2.BeginGetResponse()
WebRequest2Complete()
WebRequest1Complete()
calling to
MoveNext()
Т еперь рабочий метод В качес тве метода обработки
(WorkerMethod) может обработать завершения ас инхронной
завершенные операции и начать операции передаетс я метод
новые ас инхронные операции. клас с а AsyncEnumerator-а.
41. Пример использования класса
AsyncEnumerator
private IEnumerator<int> GetWebData(AsyncEnumerator enumerator)
{
// Начинаем несколько асинхронных операций
WebRequest webRequest1 = WebRequest.Create(url1);
webRequest1.BeginGetResponse(enumerator.End(), null);
WebRequest webRequest2 = WebRequest.Create(url2);
webRequest2.BeginGetResponse(enumerator.End(), null);
yield return 2; // 2 - это количество асинхронных операций
// Сюда мы попадем уже тогда, когда все асинхронные операции завершены
WebResponse webResponse1 = webRequest1.EndGetResponse(enumerator.DequeueAsyncResult());
WebResponse webResponse2 = webRequest2.EndGetResponse(enumerator.DequeueAsyncResult());
// Обрабатываем полученные результаты аналогичным образом
}
42. Пример использования класса
AsyncEnumerator
private void receiveDataButton_Click(object sender, EventArgs e)
{
asyncEnumerator = new AsyncEnumerator();
// AsyncEnumerator автоматически запоминает контекст синхронизации
// Запускаем процесс получения данных асинхронно
asyncEnumerator.BeginExecute(GetWebData(asyncEnumerator),
asyncEnumerator.EndExecute);
}
43. Рассматриваемые темы
Модель синхронного программирования
Паттерны асинхронного
программирования на платформе .Net
Недостатки существующих моделей
Библиотека PowerThreading
Библиотека TPL
C# 5.0: async и await
45. Ключевые классы
Task – инкапсулирует единицу работы
Task<TResult> - единица работы с определенным
типом результата
TaskFactory, TaskFactory<TResult> – фабрики
создания задач
TaskScheduler – управляет «расписанием» запуска
задач
TaskCompletionSource – управляет «временем жизни»
задачи
46. Класс Task<T>
Представляет собой «незавершенную
операцию» или «единицу работы»
Это может быть операция ввода/вывода,
операция в фоновом потоке, в выделенном
потоке и т.д.
Поддерживает «продолжения» с помощью
ContinueWith
var task2 = task1.ContinueWith(t => … t.Result …);
Содержит ряд вспомогательных методов:
WhenAll, WhenAny etc
47. Примеры использования
1. Простая задача
Task.Factory.StartNew(() => Console.WriteLine("Hello from a task!"));
2. Запуск задачи в выделенном потоке
Task task = Task.Factory.StartNew(
() =>
{
Console.WriteLine("Выполняем длительную операцию");
Thread.Sleep(TimeSpan.FromHours(1));
Console.WriteLine("Длительная операция завершена");
}, TaskCreationOptions.LongRunning);
48. Примеры использования
3. Получение данных от веб-узла
Task<long> task = new Task<long>(() => {
var webRequest = WebRequest.Create(url);
using (var webResponse = webRequest.GetResponse())
{
return webResponse.ContentLength;
}
}
);
task.Start();
task.Wait();
long result = task.Result;
4. Использование классического асинхронного API
var webRequest = WebRequest.Create(url);
Task<WebResponse> task = Task<WebResponse>.Factory.FromAsync(
webRequest.BeginGetResponse, webRequest.EndGetResponse, null);
task.Wait();
var response = task.Result;
49. Продолжения
Task task1 = new Task(() => Console.WriteLine("Task1..."));
Task task2 = task1.ContinueWith(t1 => Console.WriteLine("tTask2..."));
Task task3 = task2.ContinueWith(t2 => Console.WriteLine("ttTask3..."));
// Запускаем цепочку задач
Console.WriteLine("Запускаем первую задачу");
task1.Start();
Console.WriteLine("Ожидаем завершения цепочки задач");
task3.Wait();
Console.WriteLine("Все задачи завершены");
50. Продолжения
Task task1 = new Task(() => Console.WriteLine("Task1..."));
Task task2 = task1.ContinueWith(t1 => Console.WriteLine("tTask2..."));
Task task3 = task2.ContinueWith(t2 => Console.WriteLine("ttTask3..."));
// Запускаем цепочку задач
Console.WriteLine("Запускаем первую задачу");
task1.Start();
Console.WriteLine("Ожидаем завершения цепочки задач");
task3.Wait();
Console.WriteLine("Все задачи завершены");
Вывод:
(ничего не происходит, поскольку задача еще не запущена)
51. Продолжения
Task task1 = new Task(() => Console.WriteLine("Task1..."));
Task task2 = task1.ContinueWith(t1 => Console.WriteLine("tTask2..."));
Task task3 = task2.ContinueWith(t2 => Console.WriteLine("ttTask3..."));
// Запускаем цепочку задач
Console.WriteLine("Запускаем первую задачу");
task1.Start();
Console.WriteLine("Ожидаем завершения цепочки задач");
task3.Wait();
Console.WriteLine("Все задачи завершены");
Вывод:
(все еще ничего не происходит, поскольку первая задача не запущена)
(первой задаче установлена вторая задача в виде продолжения)
52. Продолжения
Task task1 = new Task(() => Console.WriteLine("Task1..."));
Task task2 = task1.ContinueWith(t1 => Console.WriteLine("tTask2..."));
Task task3 = task2.ContinueWith(t2 => Console.WriteLine("ttTask3..."));
// Запускаем цепочку задач
Console.WriteLine("Запускаем первую задачу");
task1.Start();
Console.WriteLine("Ожидаем завершения цепочки задач");
task3.Wait();
Console.WriteLine("Все задачи завершены");
Вывод:
(все еще ничего не происходит, поскольку первая задача не запущена)
(Связке первых двух задач установлена третья задача в виде продолжения)
53. Продолжения
Task task1 = new Task(() => Console.WriteLine("Task1..."));
Task task2 = task1.ContinueWith(t1 => Console.WriteLine("tTask2..."));
Task task3 = task2.ContinueWith(t2 => Console.WriteLine("ttTask3..."));
// Запускаем цепочку задач
Console.WriteLine("Запускаем первую задачу");
task1.Start();
Console.WriteLine("Ожидаем завершения цепочки задач");
task3.Wait();
Console.WriteLine("Все задачи завершены");
Вывод:
Запускаем первую задачу
54. Продолжения
Task task1 = new Task(() => Console.WriteLine("Task1..."));
Task task2 = task1.ContinueWith(t1 => Console.WriteLine("tTask2..."));
Task task3 = task2.ContinueWith(t2 => Console.WriteLine("ttTask3..."));
// Запускаем цепочку задач
Console.WriteLine("Запускаем первую задачу");
task1.Start();
Console.WriteLine("Ожидаем завершения цепочки задач");
task3.Wait();
Console.WriteLine("Все задачи завершены");
Вывод:
Запускаем первую задачу
Ожидаем завершения цепочки задач
55. Продолжения
Task task1 = new Task(() => Console.WriteLine("Task1..."));
Task task2 = task1.ContinueWith(t1 => Console.WriteLine("tTask2..."));
Task task3 = task2.ContinueWith(t2 => Console.WriteLine("ttTask3..."));
// Запускаем цепочку задач
Console.WriteLine("Запускаем первую задачу");
task1.Start();
Console.WriteLine("Ожидаем завершения цепочки задач");
task3.Wait();
Console.WriteLine("Все задачи завершены");
Вывод:
(Выполняется первая задача)
Запускаем первую задачу
Ожидаем завершения цепочки задач
Task1...
56. Продолжения
Task task1 = new Task(() => Console.WriteLine("Task1..."));
Task task2 = task1.ContinueWith(t1 => Console.WriteLine("tTask2..."));
Task task3 = task2.ContinueWith(t2 => Console.WriteLine("ttTask3..."));
// Запускаем цепочку задач
Console.WriteLine("Запускаем первую задачу");
task1.Start();
Console.WriteLine("Ожидаем завершения цепочки задач");
task3.Wait();
Console.WriteLine("Все задачи завершены");
Вывод:
(Выполняется вторая задача, поскольку первая уже завершилась)
Запускаем первую задачу
Ожидаем завершения цепочки задач
Task1...
Task2...
57. Продолжения
Task task1 = new Task(() => Console.WriteLine("Task1..."));
Task task2 = task1.ContinueWith(t1 => Console.WriteLine("tTask2..."));
Task task3 = task2.ContinueWith(t2 => Console.WriteLine("ttTask3..."));
// Запускаем цепочку задач
Console.WriteLine("Запускаем первую задачу");
task1.Start();
Console.WriteLine("Ожидаем завершения цепочки задач");
task3.Wait();
Console.WriteLine("Все задачи завершены");
Вывод:
(Выполняется третья задача, поскольку первая и вторая уже завершились)
Запускаем первую задачу
Ожидаем завершения цепочки задач
Task1...
Task2...
Task3...
58. Продолжения
Task task1 = new Task(() => Console.WriteLine("Task1..."));
Task task2 = task1.ContinueWith(t1 => Console.WriteLine("tTask2..."));
Task task3 = task2.ContinueWith(t2 => Console.WriteLine("ttTask3..."));
// Запускаем цепочку задач
Console.WriteLine("Запускаем первую задачу");
task1.Start();
Console.WriteLine("Ожидаем завершения цепочки задач");
task3.Wait();
Console.WriteLine("Все задачи завершены");
Вывод:
(Выполняется третья задача, поскольку первая и вторая уже завершились)
Запускаем первую задачу
Ожидаем завершения цепочки задач
Task1...
Task2...
Task3...
Все задачи завершены
59. Рассматриваемые темы
Модель синхронного программирования
Паттерны асинхронного
программирования на платформе .Net
Недостатки существующих моделей
Библиотека PowerThreading
Библиотека TPL
C# 5.0: async и await
60. Модель асинхронного
программирования в C# 5
Аналогична синхронной модели
Построена по тому же принципу, что и
класс AsyncEnumerator
Использует Task<T> для асинхронных
операций
Никто не знает, когда выйдет C# 5
Сейчас доступно Async CTP (Community
Technology Preview)
61. Модель асинхронного
программирования в C# 5
Два новых ключевых слова:
async – указывает, что метод или лямбда-
выражение является асинхронным
await – является аналогом yield return и
возвращает сразу же управление
вызывающему коду до тех пор, пока
асинхронная операция не будет завершена
62. Модель асинхронного
программирования в C# 5
static async Task<long> GetWebResponseContentLength(string url)
{
var webRequest = WebRequest.Create(url);
Console.WriteLine("Перед вызовом await-a. Thread Id: {0}",
Thread.CurrentThread.ManagedThreadId);
// Начинаем асинхронную операцию
Task<WebResponse> responseTask = webRequest.GetResponseAsync();
// Ожидаем получения ответа
WebResponse webResponse = await responseTask;
Console.WriteLine("После завершения await-а. Thread Id: {0}",
Thread.CurrentThread.ManagedThreadId);
// В этой строке мы уже получили ответ от веб-узла
// можем обрабатывать результаты. Тип возвращаемого значения
// должен соответствовать обобщенному параметру класса Task
return webResponse.ContentLength;
}
63. Работа простого метода
WriteLine("Начало исполнения. Thread Id: {0}"); static async Task<long> GetWebResponseContentLength(string url)
{
Task<long> task = var webRequest = WebRequest.Create(url);
GetWebResponseContentLength(url); WriteLine("Перед вызовом await-a. Thread Id: {0}");
// ожидаем завершения асинхронной операции // Начинаем асинхронную операцию
task.Wait(); Task<WebResponse> respTsk = webRequest.GetResponseAsync();
WriteLine("ContentLength: {0}, Thread Id: {1}"); // Ожидаем получения ответа
WebResponse webResponse = await respTsk;
WriteLine("После завершения await-а. Thread Id: {0}");
Результаты:
Начало исполнения. Thread Id: 10 return webResponse.ContentLength;
}
Перед вызовом await-a. Thread Id: 10
(Асинхронная операция запущена)
64. Работа простого метода
WriteLine("Начало исполнения. Thread Id: {0}"); static async Task<long> GetWebResponseContentLength(string url)
{
Task<long> task = var webRequest = WebRequest.Create(url);
GetWebResponseContentLength(url); WriteLine("Перед вызовом await-a. Thread Id: {0}");
// ожидаем завершения асинхронной операции // Начинаем асинхронную операцию
task.Wait(); Task<WebResponse> respTsk = webRequest.GetResponseAsync();
WriteLine("ContentLength: {0}, Thread Id: {1}"); // Ожидаем получения ответа
WebResponse webResponse = await respTsk;
WriteLine("После завершения await-а. Thread Id: {0}");
Результаты: return webResponse.ContentLength;
Начало исполнения. Thread Id: 10 }
Перед вызовом await-a. Thread Id: 10
После завершения await-a. Thread Id: 14
(Эта строка выполнится только после завершения операции)
65. Работа простого метода
WriteLine("Начало исполнения. Thread Id: {0}"); static async Task<long> GetWebResponseContentLength(string url)
{
Task<long> task = var webRequest = WebRequest.Create(url);
GetWebResponseContentLength(url); WriteLine("Перед вызовом await-a. Thread Id: {0}");
// ожидаем завершения асинхронной операции // Начинаем асинхронную операцию
task.Wait(); Task<WebResponse> respTsk = webRequest.GetResponseAsync();
WriteLine("ContentLength:{0},Thread Id: {1}"); // Ожидаем получения ответа
WebResponse webResponse = await respTsk;
WriteLine("После завершения await-а. Thread Id: {0}");
Результаты: return webResponse.ContentLength;
}
Начало исполнения. Thread Id: 10
Перед вызовом await-a. Thread Id: 10
После завершения await-a. Thread Id: 14
ContentLength: 1672, Thread Id: 10
67. Модель асинхронного
программирования в C# 5
Асинхронный метод может возвращать
void – для асинхронных операций типа “fire
and forget”
Task – вызывающий код может дождаться
завершения асинхронной операции,
которая не возвращает значения
Task<T> - для асинхронной операции,
возвращающей T (string для Task<string>
etc)
68. Модель асинхронного
программирования C# 5
private async void receiveDataButton_Click(object sender, EventArgs e)
{
Stopwatch sw = Stopwatch.StartNew();
receiveDataButton.Enabled = false;
IEnumerable<Task<WebResponse>> tasks =
from url in urls
let webRequest = WebRequest.Create(url)
select webRequest.GetResponseAsync();
// Начинаем выполнять все задачи
WebResponse[] webResponses = await TaskEx.WhenAll(tasks);
// Теперь мы можем обработать результаты
long summaryContentLength = webResponses.Sum(s => s.ContentLength);
executionTimeTextBox.Text = sw.ElapsedMilliseconds.ToString();
summaryContentLengthTextBox.Text = summaryContentLength.ToString();
receiveDataButton.Enabled = true;
foreach(var wr in webResponses)
wr.Close();
}
69. Преимущества новой
асинхронной модели
Простота использования
Привычный поток исполнения
Простота обработки ошибок и
возможность использования
конструкций using, try/finally etc
try {
WebResponse[] data = await TaskEx.WhenAll(tasks);
// Обработка данных
}
catch (WebException we) {
//Обработка ошибки получения данных
}
70. Преимущества новой
асинхронной модели
Построена на основе проверенных
идиом (Iterator blocks, AsyncEnumerator,
Reactive Extensions)
Построена на основе TPL
(преимущества от ее использования
можно закладывать уже сейчас)
71. Что мы изучили?
Модель синхронного программирования
Паттерны асинхронного
программирования на платформе .Net
Недостатки существующих моделей
Библиотека PowerThreading
Библиотека TPL
C# 5.0: async и await
72. Дополнительные ссылки
Visual Studio Asynchronous Programming (http://msdn.microsoft.com/en-
us/vstudio/async.aspx)
Асинхронные операции и AsyncEnumerator
(http://sergeyteplyakov.blogspot.com/2010/10/asyncenumerator.html)
«Реактивные расширения и асинхронные операции
(http://sergeyteplyakov.blogspot.com/2010/11/blog-post.html)
Знакомство с асинхронными операциями в C# 5
(http://sergeyteplyakov.blogspot.com/2010/12/c-5.html)
Джефри Рихтер. Упрощение модели асинхронного программирования с
помощью AsyncEnumerator (http://msdn.microsoft.com/ru-
ru/magazine/cc546608.aspx)
Джеффри Рихтер. Дополнительные возможности AsyncEnumerator
(http://msdn.microsoft.com/ru-ru/magazine/cc721613.aspx)
73. Дополнительные ссылки
Итераторы в языке программирования C#
Часть 1: http://sergeyteplyakov.blogspot.com/2010/06/c-1.html
Часть 2: http://sergeyteplyakov.blogspot.com/2010/06/c-2.html
Часть 3: http://sergeyteplyakov.blogspot.com/2010/06/c-3.html
Eric Lippert. Continuation Passing Style:
http://blogs.msdn.com/b/ericlippert/archive/tags/continuation+passing+styl
e/
Reactive Extensions Official release
(http://channel9.msdn.com/Blogs/Charles/Announcing-the-Official-Release-
of-Rx)