reactive extensions (rx) explained presenter: kevin grossnicklaus august 5 th, 2011
TRANSCRIPT
Reactive Extensions (Rx) Explained
Presenter:Kevin GrossnicklausAugust 5th, 2011
Agenda
• Introductions• Talk• Additional Resources• Conclusion
Introductions
• Kevin Grossnicklaus– ArchitectNow- www.architectnow.net (2009-Present)
• President
– Washington University - CAIT Program (2003-2010)• Instructor
– SSE - www.SSEinc.com (1999-2009)• Chief Architect• Software Development Practice Leader
• Email: [email protected] • Twitter: @kvgros • Blog: blog.architectnow.net
EXPECTATIONS
Expectations
• Experience with .NET development– Samples will be in C# 4.0– VS 2010 will be used
• Basic familiarity with LINQ and some Async programming
• Lambda Expressions will be used
INTRODUCTION TO RX
IEnumerable/IEnumerator
interface IEnumerable<T>{
IEnumerator<T> GetEnumerator();}
interface IEnumerator<T> : IDisposable{
bool MoveNext();T Current { get; }void Reset();
}
Iterating Collections
var items = new string[] { “Hello”, “World” };
foreach (var x in items){
//interact with each piece of data}
//we can now assume we are done//we must also handle exceptions
IObservable/IObserver
interface IObservable<out T>{
IDisposable Subscribe(IObserver<T> observer);}
interface IObserver<in T>{
void OnNext(T value);void OnError(Exception ex);void OnCompleted();
}
IObservable/IObserver var _data = new string[] { "Hello", "World" }; var _observable = _data.ToObservable(); var _observer = _observable.Subscribe(x => Console.WriteLine(x));
var _observer2 = _observable.Subscribe( x => Console.WriteLine(x), () => Console.WriteLine("Completed")); var _observer3 = _observable.Subscribe(
x => Console.WriteLine(x), ex => Console.WriteLine("Exception: " + ex.Message),
() => Console.WriteLine("Completed"));
_observer2.Dispose();
Getting Rx Installed
• NuGet– Easiest and quickest
• Rx Home Page:– http://msdn.microsoft.com/en-us/data/gg577609
• Simply add a reference to: – System.Reactive.DLL
• Available for:– Full Framework (WPF, WinForms, server side ASP.NET, MVC, etc)– Silverlight 3 and 4– JavaScript– Windows 7 Phone– Xbox/XNA
OBSERVABLE EXTENSIONS
Subjectsusing System.Reactive.Subjects;
var _subject = new Subject<string>(); var _observer = _subject.Subscribe(x => Console.WriteLine(x)); _subject.OnNext("Rx"); _subject.OnNext("will"); _subject.OnNext("save"); _subject.OnNext("me"); _subject.OnNext("some"); _subject.OnNext("headaches");
_subject.OnCompleted();
_observer.Dispose();
Subscribingpublic static class ObservableExtensions { public static IDisposable Subscribe<TSource>(this IObservable<TSource> source); public static IDisposable Subscribe<TSource>(this IObservable<TSource> source, Action<TSource> onNext); public static IDisposable Subscribe<TSource>(this IObservable<TSource> source, Action<TSource> onNext, Action<Exception> onError); public static IDisposable Subscribe<TSource>(this IObservable<TSource> source, Action<TSource> onNext, Action onCompleted); public static IDisposable Subscribe<TSource>(this IObservable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted); }
Creation of Observables//simply call OnCompletevar empty = Observable.Empty<string>();
//Call OnNext(“Value”) and then call OnCompletevar obReturn = Observable.Return("Value");
//Raise no eventsvar never = Observable.Never<string>();
//Call OnException with the specified expectionvar throws = Observable.Throw<string>(new Exception());
//Specify a delegate to be called when anyone subscribesvar createSample = Observable.Create<string>( observable => {
observable.OnNext("a"); observable.OnNext("b"); observable.OnCompleted(); return () => Console.WriteLine("Observer has unsubscribed");
});
Creation of Observables (Cont…)//Create a range of numbersvar range = Observable.Range(10, 15);
//publish a count from 0 every specified time periodvar interval = Observable.Interval(TimeSpan.FromMilliseconds(250));
//Never call “Next” but call “Complete” when the long running operation is donevar longOperation = Observable.Start( x => ..do something that takes awhile.. );
//Generate a collection much like for (i=5, i<15, i+3) return i.ToString();var generated = Observable.Generate(5, i => i < 15, i => i.ToString(), i => i + 3);
//simply convert an existing collection or array (IEnumerable) to IObservablevar converted = MyCollection.ToObservable();
Rx LINQ Operators
• Where• Select• First• FirstOrDefault • Last • LastOrDefault • Single • Count • Min • Max • Sum • Where • GroupBy
• Take• TakeUntil• Skip• DistinctUntilChanged• Buffer• Throttle• Sample• Delay• Until• TimeOut• ..etc…etc…etc…
RX AND .NET EVENTS
The “Old Way”
txtSample.TextChanged += new TextChangedEventHandler(txtSample_TextChanged); //txtSample.TextChanged -= new TextChangedEventHandler(txtSample_TextChanged); private string _lastValue = string.Empty;
void txtSample_TextChanged(object sender, TextChangedEventArgs e) {
var _currentValue = ((TextBox)sender).Text;
if (_currentValue.Length > 5 && _currentValue != _lastValue) {
_lastValue = _currentValue; lstData.Items.Add(_currentValue);
} }
The “New Way”
var _textChanged = Observable
.FromEventPattern<EventArgs>(txtSample, "TextChanged")
.Select(x => ((TextBox)x.Sender).Text);
var _longText = _textChanged.Where(x => x.Length > 5).DistinctUntilChanged().Throttle(TimeSpan.FromSeconds(.5));
_longText.ObserveOnDispatcher().Subscribe(x => lstData.Items.Add(x));
ADDITIONAL TOPICS
Additional Topics
• Threading– Scheduler
• Async Pattern• Attaching/Detaching
• When should I use Rx?
FINAL THOUGHTS
Additional Resources• Rx Homepage
– http://msdn.microsoft.com/en-us/devlabs/gg577609
• Rx Beginners Guide (Tutorials, Videos, etc)– http://msdn.microsoft.com/en-us/devlabs/gg577611
• Great Keynote Overview– http://channel9.msdn.com/posts/DC2010T0100-Keynote-Rx-curing-your-asynchronous-programming-blues
• Team Blog– http://blogs.msdn.com/b/rxteam/
• Community Rx Wiki– http://rxwiki.wikidot.com/
• Channel 9 Videos– http://channel9.msdn.com/tags/Rx/
• RxSandbox– http://mnajder.blogspot.com/2010/03/rxsandbox-v1.html
• Great Blog Series by Lee Campbell– http://leecampbell.blogspot.com/2010/08/reactive-extensions-for-net.html