asynchronous programming in .net (ua)
TRANSCRIPT
![Page 1: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/1.jpg)
Асинхронне програмування в .NET
Олександр Павлишак
травень 2012
![Page 2: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/2.jpg)
Для кого
Початківці
Ідея асинхронності
Базові техніки
Досвідчені
Поточний стан справ
Нові бібліотеки та підходи
Структуризація, порівняння
Outside .NET
Нові ідеї, розширення світогляду
![Page 3: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/3.jpg)
План
Асинхронність intro
Asynchronous Programming Model (APM)
Tasks (Task Parallel Library)
Reactive Extensions (Rx)
C# 5.0 async
![Page 4: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/4.jpg)
Асинхронність
– Ініціювати виконання операції
– Не чекати поки операція закінчиться,
– а одразу повернути виконання
– Продовжувати займатись іншими справами
– Могти скасувати операцію
– Отримати сповіщення про результат операції (успішний/неуспішний)(callback)
== відсутність блокування
![Page 5: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/5.jpg)
На клієнті
UI потік не можна блокувати
Типові асинхронні операції:
– Запити до серверів (веб, БД, sockets) – IO bound
– Читання/запис на диск – IO bound
– Довготривалі обчислення – CPU bound
Основна незручність:
– результат асинхронної операції повинен бути оброблений в UI потоці
Основна мета – responsiveness
![Page 6: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/6.jpg)
Бажане функціонування UI потоку
– Багато дрібних подій, виконання кожної з яких швидко завершується
– Події – message pump events + async operations callbacks
– Новим подіям не приходиться довго чекати на початок виконання
![Page 7: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/7.jpg)
Hardware працює асинхронно
CPU не блокується на операціях з пам’яттю, диском, мережевим адаптером
Всі IO пристрої володіють затримкою (latency)
Непередбачуваною
Підтримка OS: Completion ports
Недолік –програмна модель досить складна
O RLY?
![Page 8: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/8.jpg)
IO-bound задачі можуть виконуватись фоново (на апаратному рівні)
Як наслідок:
Не потрібні лишні потоки програми з логікою обробки результатів IO
Цим може займатись UI потік,
якщо ця обробка швидка.
Потрібна зручна абстракціяCompletion ports занадто низькорівневі
Плюс є ще CPU-bound задачі
![Page 9: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/9.jpg)
На сервері
Задача – обробляти багато клієнтських запитів одночасно
(concurrency)
Модель IIS + ASP.NET: 1 request – 1 thread1000 запитів – 1000 потоків
1000 запитів – 30 потоків + 970 запитів в черзі
Оптимальна кількість потоків = кількості CPU
Неефективне використання ресурсів:Більшість часу потоки чекають на IO
А коли прокидаються, конкурують за CPU
Основна мета – масштабованість (scalability)
![Page 10: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/10.jpg)
Responsiveness and scalabilityдві мети асинхронного програмування
Callbacksзасіб реалізації, який володіє проблеми :(
Потрібне розширення абстракції callback’a,а також кращі абстракції замість callback’ів
![Page 11: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/11.jpg)
Простий випадок: виконуємо одну операцію асинхронно(лише happy path)
Demo:
UI (load/save values)APM (Asynchronous Programming Model)
Альтернативи: окремий потік + UI через dispatcher
ASP.NET (call web service)APM
приклади тут
![Page 12: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/12.jpg)
stream.BeginRead(buffer, 0, buffer.Length, asyncResult =>{
context.Post(_ =>{
try{
stream.EndRead(asyncResult);stream.Dispose();Input = Encoding.ASCII.GetString(buffer);
}catch{
Input = "Error!!!";}finally{
DisplayLoadCompletedNotification();}
}, null);}, null);
Can throw
Execute in UI thread
Does not block
Does not block here
Captured in closure
“Awesomeness” of callbacks
![Page 13: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/13.jpg)
Все ускладнюється
Обробка помилок
Cancellation
Запуск багатьох операцій послідовно
Запуск декількох операцій паралельно+ після закінчення сповістити користувача
Координація операційпісля закінчення двох викликів запустити третій
...));}}}));
Wait, this is not LISP!
![Page 14: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/14.jpg)
APM
Запуск: fileStream.BeginRead(…)
Callback: BeginRead(…, asyncResult => { … }, …)Викликає EndRead()
SynchronizationContext – щоб повернутись в UI потік
Результат: виклик EndRead()
Exceptions: виклик EndRead()try…catch навколо EndRead() всередині callback
Де:Thread from IO thread pool
Явне використання SynchronizationContext.Post()
Composition: :(
![Page 15: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/15.jpg)
Futures and Promises
Розділення ініціювання операції від отримання результату
Func<>, Action<> – навпаки
Реалізація – Task<T>Обох понять, future and promise
Обох видів, IO-bound and CPU-bound
Block on Task.Result
Continuation with Task.ContinueWith()
Task.Result повідомляє про Exception
![Page 16: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/16.jpg)
RestoreInput().ContinueWith(restoreInputTask =>
{try{
Input = restoreInputTask.Result;}catch{
Input = "Error!!!";}finally{
DisplayLoadCompletedNotification();}
}, TaskScheduler.FromCurrentSynchronizationContext());
Returns Task<string> Called when task completes
Does not block Rethrows
Where to execute continuation
Already started
In UI thread
Task returned by RestoreInput()
We can schedule several continuations
![Page 17: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/17.jpg)
Task<string> RestoreInput(){
return Task.Factory.StartNew(() =>{
return File.ReadAllText("savedInput.txt");});
}
Returns started task
Runs in thread poolby default
Exception will be re-thrown in Task.Result
Can specify Scheduler
![Page 18: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/18.jpg)
Запуск Task’ів
TaskFactory.FromAsync()Адаптація APM-моделі до Task-моделі
TaskFactory.StartNew(() => { return …; })Адаптація будь-якої моделі до Task
Вказується TaskScheduler
Вказується CancellationToken
![Page 19: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/19.jpg)
Demo
Save/load values with TPL
![Page 20: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/20.jpg)
Tasks
Запуск: TaskFactory.FromAsync()TaskFactory.StartNew()
Callback: Task.ContinueWith()Викликає Task.Result
Результат: Task.Result in continuationExceptions: виклик Task.Result
try…catch навколо Task.Result всередині callbackTask.Exception, Task.IsFaulted, Task.Status
Де:При запуску вказується TaskSchedulerВ ContinueWith() вказується TaskScheduler
Composition: ContinueWith(), WhenAll/Any()
![Page 21: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/21.jpg)
Events
Корисна абстракція, не лише для UIFirst class (F#), Delegates (C#), GOF-style Observers
Single events: button click, request received
Event streams: mouse moves,key presses, stream of tweets
Події часто асинхронніПроблема – погано компонуються
Unless first class
![Page 22: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/22.jpg)
Уявіть композицію
Швидкий пошук, фільтр
![Page 23: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/23.jpg)
Уявіть композицію
По суті – серія подій OnTextChanged
Рядок повинен обрізатись – String.Trim()Tabs spaces; multiple spaces single space
Рядки із спец. символами повинні виключатись
Запуск пошуку – коли користувач перестане друкувати – throttling
Пошук лише значень, які відрізняються(послідовних) – distinct
Відображення результату останнього пошуку а не того, який прийшов найпізніше
Запис в історію пошуку
IFs, IFs, IFs
Timer
Shared mutable var
More mutable state
Multiple subscribers
![Page 24: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/24.jpg)
Reactive Extensions
Серія OnTextChanged = stream of TextBox.Texts
Звучить як... IEnumerable<string>?Pull-based: T MoveNext(void)
IObservable<string>!Push-based: void OnNext(T)
Functional Programming! Monads! Composition! Pure functions! Say No to Mutable State! Support cancer research!
Lambda
![Page 25: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/25.jpg)
Observer ≈≈ Iterator
interface IEnumerator<out T>{
T Current { get; }
bool MoveNext(void);}
interface IObserver<in T>
{
void OnNext(T);
void OnError(Exception);
void OnCompleted();
}
interface X<out T>{
T|Exception X(void)
bool X(void);}
interface X<in T>
{
void X(T);
void X(Exception);
void X(bool);
}
![Page 26: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/26.jpg)
Observer ≈≈ Iterator
interface IObservable<out T>
{
IDisposable Subscribe(Observer<T>);
}
interface IEnumerable<out T>
{
IEnumerator<T> GetEnumerator(void);
}
textChanges.Select(s => s.Trim()).Where(s => s != "").Subscribe(onNext:
s => Console.WriteLine(s));
IObservable<string>IObservable<string>
Runs on each received string
Can also pass onError, onCompleted
Returns IDisposable for un-subscription
![Page 27: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/27.jpg)
Reactive Extensions (Rx)
A library for composing asynchronous and event-based programs using observable
sequences and LINQ-style query operators.
Rx = Observables + LINQ + Schedulers
Official site
![Page 28: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/28.jpg)
Demo
Single event – Save/Load settings
Event stream – TextBox.Text changes
![Page 29: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/29.jpg)
Rx
Запуск: багато шляхів, включаючи:Observable.Return(), Observable.FromAsyncPattern()
Callback: IObserver.OnNext()IObservable.Subscribe(item => { … })
Результат: IObserver.OnNext()
Exceptions:IObserver.OnError(Exception)
Catch(), Finally(), OnErrorResumeNext() combinators
Де:ObserveOn(IScheduler)
Composition: широкий набір комбінаторів, LINQ
![Page 30: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/30.jpg)
Rx – функціональний шлях вирішення проблем з асинхронністю
та concurrency
Як щодо імперативного стилю?
Monads! Composition! Purity!
![Page 31: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/31.jpg)
Імперативний стиль
Наскільки sync код відрізняється від async?
Суттєво відрізняється!
хіба що ви програмували у функціональному стилі з самого початку
Як конвертувати sync код в async?
Перетворювати в continuations – CPS
Як бути з while/for/foreach?
try…catch? finally? using() {…}?
hint hint :)
![Page 32: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/32.jpg)
Після перетворення
Перетворений код буде
– Рекурсивний (tail recursion, anyone?)
– Реалізовувати машину станів (goto is back!)
Хороша новина: така трансформація є механічна
Compiler can do it automagicallyforeach
yield return
Pattern-based
foreach over non-IEnumerable
![Page 33: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/33.jpg)
Імперативний sync код
try{
DisplayLoadingInProgressNotification();Input = RestoreInput();
}catch{
Input = "Error!!!";}finally{
DisplayLoadCompletedNotification();}
![Page 34: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/34.jpg)
async
try{
DisplayLoadingInProgressNotification();Input = await RestoreInput();
}catch{
Input = "Error!!!";}finally{
DisplayLoadCompletedNotification();}
![Page 35: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/35.jpg)
Ще приклад: цикл
try{
DisplayLoadingInProgressNotification();foreach (var textBox in InputTextBoxes){
try{
textBox.Text = RestoreInput(GetFileName(textBox));
}catch{ textBox.Text = "Error!!!"; }
}}finally{ DisplayLoadCompletedNotification(); }
![Page 36: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/36.jpg)
async з циклом
try{
DisplayLoadingInProgressNotification();foreach (var textBox in InputTextBoxes){
try{
textBox.Text = await RestoreInput(GetFileName(textBox));
}catch{ textBox.Text = "Error!!!"; }
}}finally{ DisplayLoadCompletedNotification(); }
![Page 37: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/37.jpg)
await non-thread-pool Task
async Task<string> RestoreInput(){
using (var reader = File.OpenText("savedInput.txt")){
var result = await reader.ReadToEndAsync();Debug.WriteLine("Input restored from file.");return result;
}}
![Page 38: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/38.jpg)
await thread-pool Tasks
if (File.Exists(fileName))
return await Task.Run(() =>
{
return File.ReadAllText(fileName);
});
else
return String.Empty;
![Page 39: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/39.jpg)
Demo
async save/load value
async save/load multiple values in sequence
async save/load multiple values in parallel
![Page 40: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/40.jpg)
async, await
Запуск: call async APIReturning Task, WinRT or any awaitable
Callback: код, який слідує після awaitабо Task.ContinueWith()
Результат: await
Exceptions: await
Де: в поточному SynchronizationContextМожна також заборонити context capturing;
Composition: імперативний кодТакож Tasks
![Page 41: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/41.jpg)
APM, Tasks, Rx, asyncAPM
- Callback model
- Композиція складна
Tasks+/- Callbacks
+ Краща композиція, обробка помилок, cancellation
Rx++ Композиція, обробка помилок та cancellationу функціональному стилі
- Learning curve
async+/- Композиція, обробка помилок в імперативному стилі
+ Конвертується в Tasks
![Page 42: Asynchronous programming in .NET (UA)](https://reader030.vdocuments.mx/reader030/viewer/2022013118/55a94ba61a28abc6248b4689/html5/thumbnails/42.jpg)
Дякую за увагу!
TPL Home Team Blog Free book Other book
Reactive Extensions Home C9-Videos Intro
async Home Spec Jon Skeet InfoQ WinRT Deep
Презентація slideshare.net/opavlyshak
Приклади github.com/opavlyshak/dotNet-async-demos
@pavlyshak