reactive extensions
DESCRIPTION
Введение в реактивные расширения.Видео доклада: http://getdev.net/Event/reactive-extensionsTRANSCRIPT
Реактивные расширения
Сергей ЗвягинIngate Development
Специально для GetDev.NET
для чайников
Реактивное программирование
• Реактивное программирование — парадигма программирования, ориентированная на потоки данных и распространение изменений. Это означает, что должна существовать возможность легко выражать статические и динамические потоки данных, а также то, что выполняемая модель должна автоматически распространять изменения сквозь поток данных.
http://ru.wikipedia.org/wiki/Реактивное_программирование
Push и Pull
• Существует 2 подхода обработки последовательности данных
• При push-подходе цель запрашивает у источника содержимое
• При pull-подходе источник информирует цель о наличии данных
Push-подход
• Чтение из файла• Суммирования элементов массива• Обработка выборки из БД
Pull-подход
• Обработка действий пользователя• Получение данных от веб-сервиса• Таймеры• Анимация пользовательского интерфейса
Push-подход
• Push-коллекции в .NET реализуются с использованием интерфейсов IEnumerable<T> и IEnumerator<T>
• Это могут быть коллекции в памяти (списки, массивы), бесконечные последовательности (генераторы) или наборы данных с неизвестным заранее размером (выборка из БД)
• LINQ позволяет быстро организовать работу с такими коллекциями
Pull-подход
• События и делегаты• Асинхронные методы BeginXXXX и EndXXXX• async/await• Сторонние реализации• Да и зачем тут LINQ?
Типичные задачи
• Как обработать двойной клик?• А тройной клик?• Как проверять орфографию в словах,
которые вводит пользователь в поле?• Когда делать запросы в базу при
реализации элемента управления «живой поиск»?
Pull-подход
• В .NET 4 появилось 2 новых интерфейса, реализующих pull-подход - IObservable<T> и IObserver<T>
Простой пример
• Push-коллекция
• Pull-коллекция
.NET Rx сборки
• System.CoreEx• System.Interactive• System.Observable• System.Reactive• System.Threading
Реактивные расширения
• Представление асинхронных потоков данных как Observable
• Формирование запросов с помощью LINQ• Параметризация конкурентных
асинхронных потоков с помощью Schedulers
• Rx = Observables + LINQ + Schedulers
Операторы LINQ
• Примитивы• Создание последовательностей• Конвертация• Комбинация• Математические операции• Временные операции• Фильтрация и выбор• Обработка исключений• Функциональные операции• Специальные операции
Примитивы
• Never• Empty• Return• Throw
Создание последовательностей
• Create• Generate• Defer• Range
Конвертация
• FromAsyncPattern• FromEvent• FromEventPattern• ToObservable• ToEnumerable
Комбинация
• Amb• Concat• StartWith• Merge• Repeat• Zip
Математические операции
• Aggregate• Count• Min• Max• Sum
Временные операции
• Delay• Interval• TimeInterval• Timestamp• Timeout
Фильтрация и выбор
• Take• TakeUntil/TakeWhile• Select• SelectMany• Skip• SkipUntil/SkipWhile
Обработка исключений
• Catch• Finally• Retry• OnErrorResumeNext
Функциональные операции
• Let• Prune• Publish• Replay
Специальные операции
• Do• Run• Remotable
Многопоточность
• В каком потоке будет обрабатываться результирующая функция?– В текущем потоке– В новом потоке– В тредпуле– В потоке интерфейса
Schedulers
• Для управления конкурентными асинхронными потоками используются объекты, реализующие интерфейс IScheduler
• По умолчанию используется наиболее подходящий Scheduler
• Можно принудительно указать, какой Scheduler будет использоваться в конкретном случае
Scheduler по умолчанию
• Небольшое количество событий – ImmediateScheduler
• Большое или неопределенное количество событий – CurrentThreadScheduler
• При использовании таймеров - ThreadPoolScheduler
Использование Scheduler
• Используются статические свойства класса System.Reactive.Concurrency.Scheduler
• Указать Scheduler можно либо параметром в перегруженном методе оператораObservable.Timer(Timespan.FromSeconds(0.01), Scheduler.DispatcherScheduler).Subscribe(…);
• Либо с использованием специального оператора ObserveOnObservable.Timer(Timespan.FromSeconds(0.01)) .ObserveOn(Scheduler.DispatcherScheduler) .Subscribe(…);
Пример запросаObservable.FromEvent<TextChangedEventArgs> (searchTextBox, "TextChanged") .Select(e => ((TextBox)e.Sender).Text) .Where(text => text.Length > 2) .Do(s => searchResults.Opacity = 0.5) .Throttle(TimeSpan.FromMilliseconds(400)) .ObserveOnDispatcher() .Do(s => Indicator.Visibility = Visibility.Visible) .SelectMany(txt => searchTwitter(txt)) .Select(searchRes => ParseTwitterSearch(searchRes)) .ObserveOnDispatcher() .Do(s => Indicator.Visibility = Visibility.Collapsed) .Do(s => searchResults.Opacity = 1) .Subscribe(tweets => searchResults.ItemsSource = tweets);
Где можно использовать?
• .NET Framework 3.5 SP1• .NET Framework 4• Silverlight 4• Silverlight 5• Windows Phone 7• Windows Phone 7.1 “Mango”• .NET Framework 4.5 + WinRT (Experimental)• JavaScript
JavaScript
• Библиотека RxJS доступна в экспериментальной версии
• Логика работы повторяет логику Rx .NET• Bridges – дополнительные конвертеры
Bridges
• FromDOMEvent
var canvas = document.getElementById("canvas");var source = Rx.Observable.FromDOMEvent(canvas, "mousemove");
source.Subscribe(function(ev) { // Handle the mousemove event here});
Bridges
• FromJQuery
Rx.Observable.FromJQuery($("div, span"), "click") .Subscribe(function(evt) { $("position").html("Mouse at " + evt.pageX + ", " + evt.pageY); });
Bridges
• XmlHttpRequest
function searchWikipedia(term) { var url = "http://en.wikipedia.org/w/api.php" + "?action=opensearch&search=" + term + "&format=json";
return Rx.Observable.XmlHttpRequest(url) .Select(function(result) { var response = eval(result.responseText); if (response.length == 2) return response[1]; else return []; });}
Пример запросаvar input = $("#searchInput");var words = input.ToObservable("keyup") .Select(function(_) { return input.val(); }) .Throttle(500) .DistinctUntilChanged() .Select(function(term) { return search(term); }) .Switch();words.Subscribe(function(data) { $("#results").empty(); $.each(data, function(_, value) { $("#results").append("<li>" + value + "</li>"); }});
ВОПРОСЫ?На этом всё…
Полезные ссылки
• Reactive Extensions Developer Center http://msdn.microsoft.com/en-us/data/gg577609
• Reactive Framework Wiki http://rxwiki.wikidot.com/
• Rx Team Blog http://blogs.msdn.com/b/rxteam/
• Скачать Rx http://msdn.microsoft.com/en-us/data/gg577610
Следующая встреча
Если будут ещё вопросы – пишите!Сергей Звягин, Ingate Development• E-mail: [email protected]• Twitter: @Bingo87• Xbox: BingoRUS
Специально для GetDev.NET
Спасибо за внимание!