Top Banner
Асинхронне програмування в .NET Олександр Павлишак травень 2012
42

Asynchronous programming in .NET (UA)

Jul 18, 2015

Download

Technology

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Asynchronous programming in .NET (UA)

Асинхронне програмування в .NET

Олександр Павлишак

травень 2012

Page 2: Asynchronous programming in .NET (UA)

Для кого

Початківці

Ідея асинхронності

Базові техніки

Досвідчені

Поточний стан справ

Нові бібліотеки та підходи

Структуризація, порівняння

Outside .NET

Нові ідеї, розширення світогляду

Page 3: Asynchronous programming in .NET (UA)

План

Асинхронність intro

Asynchronous Programming Model (APM)

Tasks (Task Parallel Library)

Reactive Extensions (Rx)

C# 5.0 async

Page 4: Asynchronous programming in .NET (UA)

Асинхронність

– Ініціювати виконання операції

– Не чекати поки операція закінчиться,

– а одразу повернути виконання

– Продовжувати займатись іншими справами

– Могти скасувати операцію

– Отримати сповіщення про результат операції (успішний/неуспішний)(callback)

== відсутність блокування

Page 5: Asynchronous programming in .NET (UA)

На клієнті

UI потік не можна блокувати

Типові асинхронні операції:

– Запити до серверів (веб, БД, sockets) – IO bound

– Читання/запис на диск – IO bound

– Довготривалі обчислення – CPU bound

Основна незручність:

– результат асинхронної операції повинен бути оброблений в UI потоці

Основна мета – responsiveness

Page 6: Asynchronous programming in .NET (UA)

Бажане функціонування UI потоку

– Багато дрібних подій, виконання кожної з яких швидко завершується

– Події – message pump events + async operations callbacks

– Новим подіям не приходиться довго чекати на початок виконання

Page 7: Asynchronous programming in .NET (UA)

Hardware працює асинхронно

CPU не блокується на операціях з пам’яттю, диском, мережевим адаптером

Всі IO пристрої володіють затримкою (latency)

Непередбачуваною

Підтримка OS: Completion ports

Недолік –програмна модель досить складна

O RLY?

Page 8: Asynchronous programming in .NET (UA)

IO-bound задачі можуть виконуватись фоново (на апаратному рівні)

Як наслідок:

Не потрібні лишні потоки програми з логікою обробки результатів IO

Цим може займатись UI потік,

якщо ця обробка швидка.

Потрібна зручна абстракціяCompletion ports занадто низькорівневі

Плюс є ще CPU-bound задачі

Page 9: Asynchronous programming in .NET (UA)

На сервері

Задача – обробляти багато клієнтських запитів одночасно

(concurrency)

Модель IIS + ASP.NET: 1 request – 1 thread1000 запитів – 1000 потоків

1000 запитів – 30 потоків + 970 запитів в черзі

Оптимальна кількість потоків = кількості CPU

Неефективне використання ресурсів:Більшість часу потоки чекають на IO

А коли прокидаються, конкурують за CPU

Основна мета – масштабованість (scalability)

Page 10: Asynchronous programming in .NET (UA)

Responsiveness and scalabilityдві мети асинхронного програмування

Callbacksзасіб реалізації, який володіє проблеми :(

Потрібне розширення абстракції callback’a,а також кращі абстракції замість callback’ів

Page 11: Asynchronous programming in .NET (UA)

Простий випадок: виконуємо одну операцію асинхронно(лише 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)

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)

Все ускладнюється

Обробка помилок

Cancellation

Запуск багатьох операцій послідовно

Запуск декількох операцій паралельно+ після закінчення сповістити користувача

Координація операційпісля закінчення двох викликів запустити третій

...));}}}));

Wait, this is not LISP!

Page 14: Asynchronous programming in .NET (UA)

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)

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)

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)

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)

Запуск Task’ів

TaskFactory.FromAsync()Адаптація APM-моделі до Task-моделі

TaskFactory.StartNew(() => { return …; })Адаптація будь-якої моделі до Task

Вказується TaskScheduler

Вказується CancellationToken

Page 19: Asynchronous programming in .NET (UA)

Demo

Save/load values with TPL

Page 20: Asynchronous programming in .NET (UA)

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)

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)

Уявіть композицію

Швидкий пошук, фільтр

Page 23: Asynchronous programming in .NET (UA)

Уявіть композицію

По суті – серія подій 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)

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)

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)

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)

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)

Demo

Single event – Save/Load settings

Event stream – TextBox.Text changes

Page 29: Asynchronous programming in .NET (UA)

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)

Rx – функціональний шлях вирішення проблем з асинхронністю

та concurrency

Як щодо імперативного стилю?

Monads! Composition! Purity!

Page 31: Asynchronous programming in .NET (UA)

Імперативний стиль

Наскільки sync код відрізняється від async?

Суттєво відрізняється!

хіба що ви програмували у функціональному стилі з самого початку

Як конвертувати sync код в async?

Перетворювати в continuations – CPS

Як бути з while/for/foreach?

try…catch? finally? using() {…}?

hint hint :)

Page 32: Asynchronous programming in .NET (UA)

Після перетворення

Перетворений код буде

– Рекурсивний (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)

Імперативний sync код

try{

DisplayLoadingInProgressNotification();Input = RestoreInput();

}catch{

Input = "Error!!!";}finally{

DisplayLoadCompletedNotification();}

Page 34: Asynchronous programming in .NET (UA)

async

try{

DisplayLoadingInProgressNotification();Input = await RestoreInput();

}catch{

Input = "Error!!!";}finally{

DisplayLoadCompletedNotification();}

Page 35: Asynchronous programming in .NET (UA)

Ще приклад: цикл

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)

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)

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)

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)

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)

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)

APM, Tasks, Rx, asyncAPM

- Callback model

- Композиція складна

Tasks+/- Callbacks

+ Краща композиція, обробка помилок, cancellation

Rx++ Композиція, обробка помилок та cancellationу функціональному стилі

- Learning curve

async+/- Композиція, обробка помилок в імперативному стилі

+ Конвертується в Tasks

Page 42: Asynchronous programming in .NET (UA)

Дякую за увагу!

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

[email protected]