SlideShare a Scribd company logo
Rx .NET
Stas Rivkin
From inside out
@stas_rivkin
2
@stas_rivkin
Tasks
Not lazy
Not restartble
Feature description
Testable
3
Why Rx?
@stas_rivkin
Agenda
History
Build the Rx API – Observables inside-out
• All about the callbacks
• First building blocks
• Different Rx operators
Live demos
• Google search
• Drag and drop
“Cold” vs “Hot”
Summary & references
4
@stas_rivkin
About Me
More than 6 years of hands on with various technologies
• .NET stack (desktop mainly)
• Angular
• NodeJS
https://blog.oz-code.com/author/stasr
5
@stas_rivkin
Senior software consultant
interface IEnumerable<out T>
{
IEnumerator<T> GetEnumerator();
}
interface IObserver<in T>
{
void OnNext(T value);
void OnError(Exception error);
void OnCompleted();
}
interface IEnumerable<out T>
{
IEnumerator<T> GetEnumerator();
}
Eric Meijer
Push & Pull models
https://goo.gl/2wzXbe
PRO Tip – 36m:00
2009 – Rx released
Rx History
6
@stas_rivkin
interface IObservable<out T>
{
IDisposable Subscribe(IObserver<T> obs);
}
interface IEnumerator<out T>: IDisposable
{
bool MoveNext();
T Current { get; }
}
interface IEnumerator<out T>: IDisposable
{
bool MoveNext();
T Current { get; }
}
static void Main(string[] args)
{
Console.WriteLine("Before");
var list = new List<int>(new[] { 10, 20, 30, 40, 50, 60 });
list.ForEach(num => Console.WriteLine(num));
Console.WriteLine("After");
}
All About the Callbacks
7
@stas_rivkin
public class Program
{
static void Main(string[] args)
{
Button myBtn = new Button();
myBtn.Click += MyBtnOnClick;
}
private static void MyBtnOnClick(object sender, EventArgs eventArgs)
{
Console.WriteLine("Clicked");
}
}
public class Button
{
public event EventHandler Click;
public void RaiseClickEvent() => Click?.Invoke(this, EventArgs.Empty);
}
All About the Callbacks
8
@stas_rivkin
static async Task Main(string[] args) => await RunAsync(OnNext);
private static async Task RunAsync(
Action<string> onNext)
{
WebClient client = new WebClient();
onNext(await client.DownloadStringTaskAsync(“some-URL”));
}
private static void OnNext(string value) => Console.WriteLine(value);
All About the Callbacks
9
@stas_rivkin
static async Task Main(string[] args) => await RunAsync(OnNext, OnError)
private static async Task RunAsync(
Action<string> onNext,
Action<Exception> onError)
{
WebClient client = new WebClient();
try
{
onNext(await client.DownloadStringTaskAsync(“some-URL”));
}
catch (Exception e) { onError(e); }
}
private static void OnNext(string value) => Console.WriteLine(value);
private static void OnError(Exception e) => Console.WriteLine($":( {e}");
All About the Callbacks
10
@stas_rivkin
static async Task Main(string[] args) => await RunAsync(OnNext, OnError, OnCompleted);
private static async Task RunAsync(
Action<string> onNext,
Action<Exception> onError,
Action onCompleted)
{
WebClient client = new WebClient();
try
{
foreach (var id in new []{1,2,3})
{
onNext(await client.DownloadStringTaskAsync($“some-URL/{id}”));
}
onCompleted();
}
catch (Exception e) { onError(e); }
}
private static void OnNext(string value) => Console.WriteLine(value);
private static void OnError(Exception e) => Console.WriteLine($":( {e}");
private static void OnCompleted() => Console.WriteLine("Hooray!");
All About the Callbacks
11
@stas_rivkin
12
“Encapsulate
what varies”
Gang of four
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
13
//...
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
14
// ...
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
15
// ...
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
16
// ...
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
17
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
18
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
19
@stas_rivkin
var data = NeedData ();
...
public IEnumerable<int> NeedData()
=> new[] { 10, 20, 30 };
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
20
@stas_rivkin
First Building Blocks
21
static void Main(string[] args)
{
var observer = new ConsoleObserver();
NeedData(observer);
}
public static void NeedData(ConsoleObserver observer)
{
foreach (var value in new[] { 10, 20, 30 })
{
observer.OnNext(value);
}
observer.OnCompleted();
}
public class ConsoleObserver
{
public void OnNext(int value)
{ ... }
public void OnError(Exception error)
{ ... }
public void OnCompleted()
{ ... }
}
public interface IObserver<in T>
{
void OnNext(T value);
void OnError(Exception error);
void OnCompleted();
}
@stas_rivkin
First Building Blocks
22
public interface IObserver<in T>
{
void OnNext(T value);
void OnError(Exception error);
void OnCompleted();
}
static void Main(string[] args)
{
var observer = new ConsoleObserver();
NeedData(observer);
}
public static void NeedData(IObserver<int> observer)
{
foreach (var value in new[] { 10, 20, 30 })
{
observer.OnNext(value);
}
observer.OnCompleted();
}
@stas_rivkin
First Building Blocks
23
public interface IObserver<in T>
{
void OnNext(T value);
void OnError(Exception error);
void OnCompleted();
}
static void Main(string[] args)
{
var observer = new ConsoleObserver();
Subscribe(observer);
}
public static void Subscribe(IObserver<int> observer)
{
foreach (var value in new[] { 10, 20, 30 })
{
observer.OnNext(value);
}
observer.OnCompleted();
}
@stas_rivkin
public class Observable : IObservable<int>
{
public void Subscribe(IObserver<int> observer)
{
foreach (var value in new[] { 10, 20, 30 })
{
observer.OnNext(value);
}
observer.OnCompleted();
}
}
public interface IObservable<out T>
{
void Subscribe(IObserver<T> observer);
}
First Building Blocks
24
static void Main(string[] args)
{
var observer = new ConsoleObserver();
var observable = new Observable();
observable.Subscribe(observer);
}
@stas_rivkin
First Building Blocks
25
public class Observable : IObservable<int>
{
public IDisposable Subscribe(IObserver<int> observer)
{
foreach (var value in new[] { 10, 20, 30 })
{
observer.OnNext(value);
}
observer.OnCompleted();
return Disposable.Empty;
}
}
public interface IObservable<out T>
{
IDisposable Subscribe(IObserver<T> observer);
}
@stas_rivkin
static void Main(string[] args)
{
var observer = new ConsoleObserver();
var observable = new Observable();
observable.Subscribe(observer);
}
First Building Blocks
26
static void Main(string[] args)
{
var observer = new ConsoleObserver();
var observable = new Observable(new[]{ 10, 20, 30 });
observable.Subscribe(observer);
}
public class Observable : IObservable<int>
{
private IEumerable<int> _values;
public Observable(IEumerable<int> values)
=> _values = values;
public IDisposable Subscribe(IObserver<int> observer)
{
foreach (var value in _values)
{
observer.OnNext(value);
}
observer.OnCompleted();
return Disposable.Empty;
}
}
@stas_rivkin
First Building Blocks
27
public class Observable<T> : IObservable<T>
{
private IEumerable<T> _values;
public Observable(IEumerable<T> values)
=> _values = values;
public IDisposable Subscribe(IObserver<T> observer)
{
foreach (var value in _values)
{
observer.OnNext(value);
}
observer.OnCompleted();
return Disposable.Empty;
}
}
@stas_rivkin
static void Main(string[] args)
{
var observer = new ConsoleObserver();
var observable = new Observable(new[]{ 10, 20, 30 });
observable.Subscribe(observer);
}
First Building Blocks
28
public class ToObservable<T> : IObservable<T>
{
private IEnumerable<T> _values;
public ToObservable(IEnumerable<T> values)
=> _values = values;
public IDisposable Subscribe(IObserver<T> observer)
{
foreach (var value in _values)
{
observer.OnNext(value);
}
observer.OnCompleted();
return Disposable.Empty;
}
}
static void Main(string[] args)
{
var observer = new ConsoleObserver();
var observable = new ToObservable(new[]{ 10, 20, 30 });
observable.Subscribe(observer);
}
@stas_rivkin
public static class ObservableExtensions
{
public static IObservable<T> ToObservable<T>
this IEnumerable<T> src)
=> new ToObservable<T>(src);
}
static void Main(string[] args)
{
var observer = new ConsoleObserver();
IObservable observable = new[]{ 10, 20, 30 }
.ToObservable();
observable.Subscribe(observer);
}
IEnumerable -> IObservable
29
@stas_rivkin
static void Main(string[] args)
{
var observer = new ConsoleObserver();
IObservable observable = new[]{ 10, 20, 30 }
.ToObservable();
observable.Subscribe(observer);
}
Where
30
@stas_rivkin
public static class ObservableExtensions
{
public static IObservable<T> ToObservable<T>
this IEnumerable<T> src)
=> new ToObservable<T>(src);
public static IObservable<T> Where<T>(
this IObservable<T> src,
Func<T, bool> filter)
=> new Where<T>(src, filter);
}
Where
31
@stas_rivkin
public static class ObservableExtensions
{
public static IObservable<T> ToObservable<T>
this IEnumerable<T> src)
=> new ToObservable<T>(src);
public static IObservable<T> Where<T>(
this IObservable<T> src,
Func<T, bool> filter)
=> new Where<T>(src, filter);
}
static void Main(string[] args)
{
var observer = new ConsoleObserver();
IObservable observable = new[]{ 10, 20, 30 }
.ToObservable()
.Where(n => n > 10);
observable.Subscribe(observer);
}
Where
32
public class Where<T> : IObservable<T>
{
private IObservable<T> _src;
private Func<T, bool> _filter;
public Where(
IObservable<T> src,
Func<T, bool> filter)
{
_src = src;
_filter = filter;
}
public IDisposable Subscribe(IObserver<T> observer)
{
//...
}
}
@stas_rivkin
Where
33
public class Where<T> : IObservable<T>,
{
private IObservable<T> _src;
private Func<T, bool> _filter;
private IObserver<T> _observer;
public Where(
IObservable<T> src,
Func<T, bool> filter)
{
_src = src;
_filter = filter;
}
public IDisposable Subscribe(IObserver<T> observer)
{
_observer = observer;
return new CompositeDisposable
{
_src.Subscribe(this),
Disposable.Create(() => _observer = null)
};
}
/* */
}
@stas_rivkin
IObserver<T>
Where
34
public class Where<T> : IObservable<T>, IObserver<T>
{
private IObservable<T> _src;
private Func<T, bool> _filter;
private IObserver<T> _observer;
public Where(
IObservable<T> src,
Func<T, bool> filter)
{
_src = src;
_filter = filter;
}
public IDisposable Subscribe(IObserver<T> observer)
{ ... }
public void OnNext(T value)
{
if(_filter(value)) _observer.OnNext(value);
}
public void OnError(Exception error) => _observer.OnError(error);
public void OnCompleted() => _observer.OnCompleted();
}
@stas_rivkin
static void Main(string[] args)
{
var observer = new ConsoleObserver();
IObservable observable = new[]{ 10, 20, 30 }
.ToObservable()
.Where(n => n > 10);
observable.Subscribe(observer);
}
Select
35
public static class ObservableExtensions
{
public static IObservable<T> ToObservable<T>
this IEnumerable<T> src)
=> new ToObservable<T>(src);
public static IObservable<T> Where<T>(
this IObservable<T> src,
Func<T,bool> filter)
=> new Where<T>(src, filter);
public static IObservable<TOut> Select<TIn, TOut>(
this IObservable<TIn> src,
Func<TIn, TOut> selector)
=> new Select<TIn, TOut>(src, selector);
}
@stas_rivkin
Select
36
static void Main(string[] args)
{
var observer = new ConsoleObserver();
IObservable observable = new[]{ 10, 20, 30 }
.ToObservable()
.Where(n => n > 10)
.Select(n => n * 10);
observable.Subscribe(observer);
}
@stas_rivkin
public static class ObservableExtensions
{
public static IObservable<T> ToObservable<T>
this IEnumerable<T> src)
=> new ToObservable<T>(src);
public static IObservable<T> Where<T>(
this IObservable<T> src,
Func<T,bool> filter)
=> new Where<T>(src, filter);
public static IObservable<TOut> Select<TIn, TOut>(
this IObservable<TIn> src,
Func<TIn, TOut> selector)
=> new Select<TIn, TOut>(src, selector);
}
public class Select<TIn, TOut> : IObservable<TOut>, IObserver<TIn>
{
private IObservable<TIn> _src;
private Func<TIn, TOut> _selector;
private IObserver<TOut> _observer;
public Select(
IObservable<TIn> src,
Func<TIn, TOut> selector)
{
_src = src;
_selector = selector;
}
public IDisposable Subscribe(IObserver<TOut> observer)
{ ... }
public void OnNext(TIn value)
{
_observer.OnNext(_selector(value));
}
public void OnError(Exception error) => _observer.OnError(error);
public void OnCompleted() => _observer.OnCompleted();
}
Select
37
@stas_rivkin

In Action
38
static void Main(string[] args)
{
var observer = new ConsoleObserver();
IDisposable subscription = new[]{ 10, 20, 30}
.ToObservable()
.Where(n => n > 10)
.Select(n => n * 10);
.Subscribe(observer);
}
Where(n => n > 10)
Select(n => n * 10)
@stas_rivkin
Filtering Projection Partitioning Joins Grouping Set
Element Generation Quantifiers Aggregation Error HandlingTime and
Concurrency
Where
OfType
Select
SelectMany
Materialize
Skip
Take
TakeUntil
CombineLatest
Concat
join
GroupBy
GroupByUntil
Buffer
Distinct
DistinctUntilChanged
Timeout
TimeInterval
ElementAt
First
Single
Range
Repeat
Defer
All
Any
Contains
Sum
Average
Scan
Catch
OnErrorResumeNext
Using
Rx Operators
@stas_rivkin
Timestamp
Rx Packages
40
@stas_rivkin
Google Search
1. At least 3 characters
2. Don’t send the same string again
41
@stas_rivkin
Demo
43
Where(newSearchToken => newSearchToken.Length > 2 )

@stas_rivkin
44
Where(newSearchToken => newSearchToken.Length > 2 )

Throttle(TimeSpan.FromSeconds(0.5))
0.2sec

@stas_rivkin
45
Where(newSearchToken => newSearchToken.Length > 2 )

Throttle(TimeSpan.FromSeconds(0.5))
DistinctUntilChanged()
0.2sec


@stas_rivkin
46
Select(searchToken => SearchService.SearchAsync(searchToken))
REA
REAC
Switch()
REA results are ignored since we
switched to the “REAC” results

@stas_rivkin
var dragObs = mouseMoveObs.SkipUntil(mouseDownObs).TakeUntil(mouseUpObs)
Drag and Drop
47
var mouseDownObs = Observable.FromEventPattern(UIElement, nameof(UIElement.MouseDown));
var mouseMoveObs = Observable.FromEventPattern(UIElement, nameof(UIElement.MouseMove));
var mouseUpObs = Observable.FromEventPattern(UIElement, nameof(UIElement.MouseUp));
.Repeat();
On each mouse-down on your target,
start processing mouse-moves for your target
until a single mouse-up on your target
On each mouse-down on your target,
start processing mouse-moves for your target
until a single mouse-up on your target
;
@stas_rivkin
Demo
49
Select(me => me.EventArgs.GetPosition(DrawingControl))
@stas_rivkin
50
Select(me => me.EventArgs.GetPosition(DrawingControl))
SelectMany(point => itemsStream.SelectMany((item,index) => …))itemsStream.SelectMany
@stas_rivkin
51
Observable.Return(new{item,Point = new Point(point.X+index, point.y)})
[0] [1] [2] [3] [4] [n]index:
point.X+index, point.y
@stas_rivkin
“Rx can make text fly”
52
Delay(TimeSpan.FromMilliseconds(index*75), loopScheduler)
Observable.Return(new{item,Point = new Point(point.X+index, point.y)})
[0] [1] [2] [3] [4] [n]index:
[1]*75ms
[2]*75ms
[n]*75ms
@stas_rivkin
“Rx can make text fly”
53
Select(me => me.EventArgs.GetPosition(DrawingControl))
SelectMany(point => itemsStream.SelectMany((item,index) => …))
@stas_rivkin
“Cold” vs “Hot”
54
Observables are “cold” by default
•“Cold” creates a new producer each time a consumer subscribes to it
•“Hot” observables share a single producer with every consumer that
subscribes to them
var aStream = Observable.Where(...).Select(...)
aStream.Subscribe(...); var shared = aStream.Publish().RefCount();
aStream.Subscribe(...);
aStream.Subscribe(...);
shared.Subscribe(...);
shared.Subscribe(...);
shared.Subscribe(...);
@stas_rivkin
Summary
Simple idea – definitely not some magic
Easy to compose between events, callbacks, time-based operations
• Treating events as collections
• Manipulating sets of events with “operators”
Observables are LAZY by nature
• “subscribe” to the Observable sometime in the future
• “dispose” from the observable to cancel & tear down the producer
55
@stas_rivkin
www.reactivex.io
github.com/Reactive-Extensions
www.manning.com/dresher
56
Resources
@stas_rivkin
Thanks for Coming
Q
A ?
@stas_rivkin
GitHub examples:
http://bit.ly/2whyHKt

More Related Content

PPTX
(Rx).NET' way of async programming (.NET summit 2017 Belarus)
PPTX
RxJS ‘Marble’ programming
PDF
Практическое применения Akka Streams
PDF
«Практическое применение Akka Streams» — Алексей Романчук, 2ГИС
DOCX
.net progrmming part1
PPT
PDF
C Code and the Art of Obfuscation
PPT
Whats new in_csharp4
(Rx).NET' way of async programming (.NET summit 2017 Belarus)
RxJS ‘Marble’ programming
Практическое применения Akka Streams
«Практическое применение Akka Streams» — Алексей Романчук, 2ГИС
.net progrmming part1
C Code and the Art of Obfuscation
Whats new in_csharp4

What's hot (20)

PDF
54602399 c-examples-51-to-108-programe-ee01083101
DOCX
Java Program
PDF
Alexey Tsoy Meta Programming in C++ 16.11.17
PDF
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
PPTX
ZIO: Powerful and Principled Functional Programming in Scala
PDF
JavaScript 2016 for C# Developers
PDF
PDF
The Ring programming language version 1.5.2 book - Part 74 of 181
PPTX
What’s new in C# 6
DOCX
Student Data Base Using C/C++ Final Project
PDF
Меняем javascript с помощью javascript
PDF
ClojurianからみたElixir
PPTX
DOCX
C# console programms
DOCX
Oops practical file
DOC
CBSE Class XII Comp sc practical file
PPTX
C sharp 8
PDF
The Ring programming language version 1.5.4 book - Part 77 of 185
PDF
Berlin meetup
PDF
Продвинутая отладка JavaScript с помощью Chrome Dev Tools
54602399 c-examples-51-to-108-programe-ee01083101
Java Program
Alexey Tsoy Meta Programming in C++ 16.11.17
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
ZIO: Powerful and Principled Functional Programming in Scala
JavaScript 2016 for C# Developers
The Ring programming language version 1.5.2 book - Part 74 of 181
What’s new in C# 6
Student Data Base Using C/C++ Final Project
Меняем javascript с помощью javascript
ClojurianからみたElixir
C# console programms
Oops practical file
CBSE Class XII Comp sc practical file
C sharp 8
The Ring programming language version 1.5.4 book - Part 77 of 185
Berlin meetup
Продвинутая отладка JavaScript с помощью Chrome Dev Tools
Ad

Similar to Rx.NET, from the inside out - Codemotion 2018 (20)

PDF
Дмитрий Верескун «Синтаксический сахар C#»
PPTX
Effective C#
PDF
Asynchronous web apps with the Play Framework 2.0
PPTX
C# 6 and 7 and Futures 20180607
DOCX
.net progrmming part2
PPTX
NetPonto - The Future Of C# - NetConf Edition
PDF
Non Blocking I/O for Everyone with RxJava
PDF
PPTX
.NET Foundation, Future of .NET and C#
PDF
C++ practical
PDF
Think Async: Asynchronous Patterns in NodeJS
PPTX
Flow Control and Exception Handling.pptx
PPTX
Is your C# optimized
PDF
Functional Principles for OO Developers
DOCX
C# labprograms
PDF
Design Patterns - Compiler Case Study - Hands-on Examples
PDF
RESTful API using scalaz (3)
PDF
Refactoring to Macros with Clojure
PDF
greenDAO
PPTX
Tamir Dresher - What’s new in ASP.NET Core 6
Дмитрий Верескун «Синтаксический сахар C#»
Effective C#
Asynchronous web apps with the Play Framework 2.0
C# 6 and 7 and Futures 20180607
.net progrmming part2
NetPonto - The Future Of C# - NetConf Edition
Non Blocking I/O for Everyone with RxJava
.NET Foundation, Future of .NET and C#
C++ practical
Think Async: Asynchronous Patterns in NodeJS
Flow Control and Exception Handling.pptx
Is your C# optimized
Functional Principles for OO Developers
C# labprograms
Design Patterns - Compiler Case Study - Hands-on Examples
RESTful API using scalaz (3)
Refactoring to Macros with Clojure
greenDAO
Tamir Dresher - What’s new in ASP.NET Core 6
Ad

Recently uploaded (20)

PDF
Odoo Companies in India – Driving Business Transformation.pdf
PPTX
Monitoring Stack: Grafana, Loki & Promtail
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PPTX
Transform Your Business with a Software ERP System
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PPTX
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
medical staffing services at VALiNTRY
PDF
Nekopoi APK 2025 free lastest update
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Digital Systems & Binary Numbers (comprehensive )
PPTX
L1 - Introduction to python Backend.pptx
PDF
How to Make Money in the Metaverse_ Top Strategies for Beginners.pdf
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PPTX
assetexplorer- product-overview - presentation
PPTX
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
PDF
CCleaner Pro 6.38.11537 Crack Final Latest Version 2025
PDF
Download FL Studio Crack Latest version 2025 ?
DOCX
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps
Odoo Companies in India – Driving Business Transformation.pdf
Monitoring Stack: Grafana, Loki & Promtail
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Transform Your Business with a Software ERP System
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
medical staffing services at VALiNTRY
Nekopoi APK 2025 free lastest update
Design an Analysis of Algorithms I-SECS-1021-03
Digital Systems & Binary Numbers (comprehensive )
L1 - Introduction to python Backend.pptx
How to Make Money in the Metaverse_ Top Strategies for Beginners.pdf
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
How to Choose the Right IT Partner for Your Business in Malaysia
assetexplorer- product-overview - presentation
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
CCleaner Pro 6.38.11537 Crack Final Latest Version 2025
Download FL Studio Crack Latest version 2025 ?
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps

Rx.NET, from the inside out - Codemotion 2018

  • 1. Rx .NET Stas Rivkin From inside out @stas_rivkin
  • 3. Tasks Not lazy Not restartble Feature description Testable 3 Why Rx? @stas_rivkin
  • 4. Agenda History Build the Rx API – Observables inside-out • All about the callbacks • First building blocks • Different Rx operators Live demos • Google search • Drag and drop “Cold” vs “Hot” Summary & references 4 @stas_rivkin
  • 5. About Me More than 6 years of hands on with various technologies • .NET stack (desktop mainly) • Angular • NodeJS https://blog.oz-code.com/author/stasr 5 @stas_rivkin Senior software consultant
  • 6. interface IEnumerable<out T> { IEnumerator<T> GetEnumerator(); } interface IObserver<in T> { void OnNext(T value); void OnError(Exception error); void OnCompleted(); } interface IEnumerable<out T> { IEnumerator<T> GetEnumerator(); } Eric Meijer Push & Pull models https://goo.gl/2wzXbe PRO Tip – 36m:00 2009 – Rx released Rx History 6 @stas_rivkin interface IObservable<out T> { IDisposable Subscribe(IObserver<T> obs); } interface IEnumerator<out T>: IDisposable { bool MoveNext(); T Current { get; } } interface IEnumerator<out T>: IDisposable { bool MoveNext(); T Current { get; } }
  • 7. static void Main(string[] args) { Console.WriteLine("Before"); var list = new List<int>(new[] { 10, 20, 30, 40, 50, 60 }); list.ForEach(num => Console.WriteLine(num)); Console.WriteLine("After"); } All About the Callbacks 7 @stas_rivkin
  • 8. public class Program { static void Main(string[] args) { Button myBtn = new Button(); myBtn.Click += MyBtnOnClick; } private static void MyBtnOnClick(object sender, EventArgs eventArgs) { Console.WriteLine("Clicked"); } } public class Button { public event EventHandler Click; public void RaiseClickEvent() => Click?.Invoke(this, EventArgs.Empty); } All About the Callbacks 8 @stas_rivkin
  • 9. static async Task Main(string[] args) => await RunAsync(OnNext); private static async Task RunAsync( Action<string> onNext) { WebClient client = new WebClient(); onNext(await client.DownloadStringTaskAsync(“some-URL”)); } private static void OnNext(string value) => Console.WriteLine(value); All About the Callbacks 9 @stas_rivkin
  • 10. static async Task Main(string[] args) => await RunAsync(OnNext, OnError) private static async Task RunAsync( Action<string> onNext, Action<Exception> onError) { WebClient client = new WebClient(); try { onNext(await client.DownloadStringTaskAsync(“some-URL”)); } catch (Exception e) { onError(e); } } private static void OnNext(string value) => Console.WriteLine(value); private static void OnError(Exception e) => Console.WriteLine($":( {e}"); All About the Callbacks 10 @stas_rivkin
  • 11. static async Task Main(string[] args) => await RunAsync(OnNext, OnError, OnCompleted); private static async Task RunAsync( Action<string> onNext, Action<Exception> onError, Action onCompleted) { WebClient client = new WebClient(); try { foreach (var id in new []{1,2,3}) { onNext(await client.DownloadStringTaskAsync($“some-URL/{id}”)); } onCompleted(); } catch (Exception e) { onError(e); } } private static void OnNext(string value) => Console.WriteLine(value); private static void OnError(Exception e) => Console.WriteLine($":( {e}"); private static void OnCompleted() => Console.WriteLine("Hooray!"); All About the Callbacks 11 @stas_rivkin
  • 13. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 13 //... @stas_rivkin
  • 14. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 14 // ... @stas_rivkin
  • 15. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 15 // ... @stas_rivkin
  • 16. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 16 // ... @stas_rivkin
  • 17. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 17 @stas_rivkin
  • 18. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 18 @stas_rivkin
  • 19. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 19 @stas_rivkin var data = NeedData (); ... public IEnumerable<int> NeedData() => new[] { 10, 20, 30 };
  • 20. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 20 @stas_rivkin
  • 21. First Building Blocks 21 static void Main(string[] args) { var observer = new ConsoleObserver(); NeedData(observer); } public static void NeedData(ConsoleObserver observer) { foreach (var value in new[] { 10, 20, 30 }) { observer.OnNext(value); } observer.OnCompleted(); } public class ConsoleObserver { public void OnNext(int value) { ... } public void OnError(Exception error) { ... } public void OnCompleted() { ... } } public interface IObserver<in T> { void OnNext(T value); void OnError(Exception error); void OnCompleted(); } @stas_rivkin
  • 22. First Building Blocks 22 public interface IObserver<in T> { void OnNext(T value); void OnError(Exception error); void OnCompleted(); } static void Main(string[] args) { var observer = new ConsoleObserver(); NeedData(observer); } public static void NeedData(IObserver<int> observer) { foreach (var value in new[] { 10, 20, 30 }) { observer.OnNext(value); } observer.OnCompleted(); } @stas_rivkin
  • 23. First Building Blocks 23 public interface IObserver<in T> { void OnNext(T value); void OnError(Exception error); void OnCompleted(); } static void Main(string[] args) { var observer = new ConsoleObserver(); Subscribe(observer); } public static void Subscribe(IObserver<int> observer) { foreach (var value in new[] { 10, 20, 30 }) { observer.OnNext(value); } observer.OnCompleted(); } @stas_rivkin
  • 24. public class Observable : IObservable<int> { public void Subscribe(IObserver<int> observer) { foreach (var value in new[] { 10, 20, 30 }) { observer.OnNext(value); } observer.OnCompleted(); } } public interface IObservable<out T> { void Subscribe(IObserver<T> observer); } First Building Blocks 24 static void Main(string[] args) { var observer = new ConsoleObserver(); var observable = new Observable(); observable.Subscribe(observer); } @stas_rivkin
  • 25. First Building Blocks 25 public class Observable : IObservable<int> { public IDisposable Subscribe(IObserver<int> observer) { foreach (var value in new[] { 10, 20, 30 }) { observer.OnNext(value); } observer.OnCompleted(); return Disposable.Empty; } } public interface IObservable<out T> { IDisposable Subscribe(IObserver<T> observer); } @stas_rivkin static void Main(string[] args) { var observer = new ConsoleObserver(); var observable = new Observable(); observable.Subscribe(observer); }
  • 26. First Building Blocks 26 static void Main(string[] args) { var observer = new ConsoleObserver(); var observable = new Observable(new[]{ 10, 20, 30 }); observable.Subscribe(observer); } public class Observable : IObservable<int> { private IEumerable<int> _values; public Observable(IEumerable<int> values) => _values = values; public IDisposable Subscribe(IObserver<int> observer) { foreach (var value in _values) { observer.OnNext(value); } observer.OnCompleted(); return Disposable.Empty; } } @stas_rivkin
  • 27. First Building Blocks 27 public class Observable<T> : IObservable<T> { private IEumerable<T> _values; public Observable(IEumerable<T> values) => _values = values; public IDisposable Subscribe(IObserver<T> observer) { foreach (var value in _values) { observer.OnNext(value); } observer.OnCompleted(); return Disposable.Empty; } } @stas_rivkin static void Main(string[] args) { var observer = new ConsoleObserver(); var observable = new Observable(new[]{ 10, 20, 30 }); observable.Subscribe(observer); }
  • 28. First Building Blocks 28 public class ToObservable<T> : IObservable<T> { private IEnumerable<T> _values; public ToObservable(IEnumerable<T> values) => _values = values; public IDisposable Subscribe(IObserver<T> observer) { foreach (var value in _values) { observer.OnNext(value); } observer.OnCompleted(); return Disposable.Empty; } } static void Main(string[] args) { var observer = new ConsoleObserver(); var observable = new ToObservable(new[]{ 10, 20, 30 }); observable.Subscribe(observer); } @stas_rivkin
  • 29. public static class ObservableExtensions { public static IObservable<T> ToObservable<T> this IEnumerable<T> src) => new ToObservable<T>(src); } static void Main(string[] args) { var observer = new ConsoleObserver(); IObservable observable = new[]{ 10, 20, 30 } .ToObservable(); observable.Subscribe(observer); } IEnumerable -> IObservable 29 @stas_rivkin
  • 30. static void Main(string[] args) { var observer = new ConsoleObserver(); IObservable observable = new[]{ 10, 20, 30 } .ToObservable(); observable.Subscribe(observer); } Where 30 @stas_rivkin public static class ObservableExtensions { public static IObservable<T> ToObservable<T> this IEnumerable<T> src) => new ToObservable<T>(src); public static IObservable<T> Where<T>( this IObservable<T> src, Func<T, bool> filter) => new Where<T>(src, filter); }
  • 31. Where 31 @stas_rivkin public static class ObservableExtensions { public static IObservable<T> ToObservable<T> this IEnumerable<T> src) => new ToObservable<T>(src); public static IObservable<T> Where<T>( this IObservable<T> src, Func<T, bool> filter) => new Where<T>(src, filter); } static void Main(string[] args) { var observer = new ConsoleObserver(); IObservable observable = new[]{ 10, 20, 30 } .ToObservable() .Where(n => n > 10); observable.Subscribe(observer); }
  • 32. Where 32 public class Where<T> : IObservable<T> { private IObservable<T> _src; private Func<T, bool> _filter; public Where( IObservable<T> src, Func<T, bool> filter) { _src = src; _filter = filter; } public IDisposable Subscribe(IObserver<T> observer) { //... } } @stas_rivkin
  • 33. Where 33 public class Where<T> : IObservable<T>, { private IObservable<T> _src; private Func<T, bool> _filter; private IObserver<T> _observer; public Where( IObservable<T> src, Func<T, bool> filter) { _src = src; _filter = filter; } public IDisposable Subscribe(IObserver<T> observer) { _observer = observer; return new CompositeDisposable { _src.Subscribe(this), Disposable.Create(() => _observer = null) }; } /* */ } @stas_rivkin IObserver<T>
  • 34. Where 34 public class Where<T> : IObservable<T>, IObserver<T> { private IObservable<T> _src; private Func<T, bool> _filter; private IObserver<T> _observer; public Where( IObservable<T> src, Func<T, bool> filter) { _src = src; _filter = filter; } public IDisposable Subscribe(IObserver<T> observer) { ... } public void OnNext(T value) { if(_filter(value)) _observer.OnNext(value); } public void OnError(Exception error) => _observer.OnError(error); public void OnCompleted() => _observer.OnCompleted(); } @stas_rivkin
  • 35. static void Main(string[] args) { var observer = new ConsoleObserver(); IObservable observable = new[]{ 10, 20, 30 } .ToObservable() .Where(n => n > 10); observable.Subscribe(observer); } Select 35 public static class ObservableExtensions { public static IObservable<T> ToObservable<T> this IEnumerable<T> src) => new ToObservable<T>(src); public static IObservable<T> Where<T>( this IObservable<T> src, Func<T,bool> filter) => new Where<T>(src, filter); public static IObservable<TOut> Select<TIn, TOut>( this IObservable<TIn> src, Func<TIn, TOut> selector) => new Select<TIn, TOut>(src, selector); } @stas_rivkin
  • 36. Select 36 static void Main(string[] args) { var observer = new ConsoleObserver(); IObservable observable = new[]{ 10, 20, 30 } .ToObservable() .Where(n => n > 10) .Select(n => n * 10); observable.Subscribe(observer); } @stas_rivkin public static class ObservableExtensions { public static IObservable<T> ToObservable<T> this IEnumerable<T> src) => new ToObservable<T>(src); public static IObservable<T> Where<T>( this IObservable<T> src, Func<T,bool> filter) => new Where<T>(src, filter); public static IObservable<TOut> Select<TIn, TOut>( this IObservable<TIn> src, Func<TIn, TOut> selector) => new Select<TIn, TOut>(src, selector); }
  • 37. public class Select<TIn, TOut> : IObservable<TOut>, IObserver<TIn> { private IObservable<TIn> _src; private Func<TIn, TOut> _selector; private IObserver<TOut> _observer; public Select( IObservable<TIn> src, Func<TIn, TOut> selector) { _src = src; _selector = selector; } public IDisposable Subscribe(IObserver<TOut> observer) { ... } public void OnNext(TIn value) { _observer.OnNext(_selector(value)); } public void OnError(Exception error) => _observer.OnError(error); public void OnCompleted() => _observer.OnCompleted(); } Select 37 @stas_rivkin
  • 38.  In Action 38 static void Main(string[] args) { var observer = new ConsoleObserver(); IDisposable subscription = new[]{ 10, 20, 30} .ToObservable() .Where(n => n > 10) .Select(n => n * 10); .Subscribe(observer); } Where(n => n > 10) Select(n => n * 10) @stas_rivkin
  • 39. Filtering Projection Partitioning Joins Grouping Set Element Generation Quantifiers Aggregation Error HandlingTime and Concurrency Where OfType Select SelectMany Materialize Skip Take TakeUntil CombineLatest Concat join GroupBy GroupByUntil Buffer Distinct DistinctUntilChanged Timeout TimeInterval ElementAt First Single Range Repeat Defer All Any Contains Sum Average Scan Catch OnErrorResumeNext Using Rx Operators @stas_rivkin Timestamp
  • 41. Google Search 1. At least 3 characters 2. Don’t send the same string again 41 @stas_rivkin
  • 42. Demo
  • 44. 44 Where(newSearchToken => newSearchToken.Length > 2 )  Throttle(TimeSpan.FromSeconds(0.5)) 0.2sec  @stas_rivkin
  • 45. 45 Where(newSearchToken => newSearchToken.Length > 2 )  Throttle(TimeSpan.FromSeconds(0.5)) DistinctUntilChanged() 0.2sec   @stas_rivkin
  • 46. 46 Select(searchToken => SearchService.SearchAsync(searchToken)) REA REAC Switch() REA results are ignored since we switched to the “REAC” results  @stas_rivkin
  • 47. var dragObs = mouseMoveObs.SkipUntil(mouseDownObs).TakeUntil(mouseUpObs) Drag and Drop 47 var mouseDownObs = Observable.FromEventPattern(UIElement, nameof(UIElement.MouseDown)); var mouseMoveObs = Observable.FromEventPattern(UIElement, nameof(UIElement.MouseMove)); var mouseUpObs = Observable.FromEventPattern(UIElement, nameof(UIElement.MouseUp)); .Repeat(); On each mouse-down on your target, start processing mouse-moves for your target until a single mouse-up on your target On each mouse-down on your target, start processing mouse-moves for your target until a single mouse-up on your target ; @stas_rivkin
  • 48. Demo
  • 50. 50 Select(me => me.EventArgs.GetPosition(DrawingControl)) SelectMany(point => itemsStream.SelectMany((item,index) => …))itemsStream.SelectMany @stas_rivkin
  • 51. 51 Observable.Return(new{item,Point = new Point(point.X+index, point.y)}) [0] [1] [2] [3] [4] [n]index: point.X+index, point.y @stas_rivkin “Rx can make text fly”
  • 52. 52 Delay(TimeSpan.FromMilliseconds(index*75), loopScheduler) Observable.Return(new{item,Point = new Point(point.X+index, point.y)}) [0] [1] [2] [3] [4] [n]index: [1]*75ms [2]*75ms [n]*75ms @stas_rivkin “Rx can make text fly”
  • 53. 53 Select(me => me.EventArgs.GetPosition(DrawingControl)) SelectMany(point => itemsStream.SelectMany((item,index) => …)) @stas_rivkin
  • 54. “Cold” vs “Hot” 54 Observables are “cold” by default •“Cold” creates a new producer each time a consumer subscribes to it •“Hot” observables share a single producer with every consumer that subscribes to them var aStream = Observable.Where(...).Select(...) aStream.Subscribe(...); var shared = aStream.Publish().RefCount(); aStream.Subscribe(...); aStream.Subscribe(...); shared.Subscribe(...); shared.Subscribe(...); shared.Subscribe(...); @stas_rivkin
  • 55. Summary Simple idea – definitely not some magic Easy to compose between events, callbacks, time-based operations • Treating events as collections • Manipulating sets of events with “operators” Observables are LAZY by nature • “subscribe” to the Observable sometime in the future • “dispose” from the observable to cancel & tear down the producer 55 @stas_rivkin
  • 57. Thanks for Coming Q A ? @stas_rivkin GitHub examples: http://bit.ly/2whyHKt

Editor's Notes

  • #4: Don’t get me wrong! I love async-await… I think it made our async lives much more easier! But the problem with async-await is, it can’t be concise and the reason it can’t be concise is because await doesn’t help me get rid of state, immutable state. The enemy of any user-interface application. The more mutable state I have, the harder it makes me to figure out the state of my program. The other thing is, I want describe an idea, a feature - in a one readable place without going through some sort of a callback chain. Sooo thing that I’m excited about with Rx, is it allows you to write that kind of code, a lot more dependable, a lot more relible… async code I can write something.. a I’m pretty sure it is going to do what I what… Ohh… and it’s testable… I can write tests which run the same way every time…
  • #6: My name is Stas Rivkin **and you already figured out from my name, I do speak Russian. But this talk will be in English, cause frankly I have no clue how to pronounce software technicalities in Russian. I’m a software consultant @codevalue Israel. CodeValue is a consulating company and we are also the proud development center of OzCode the amazing debugging extensions for visual studio. Few of it’s key features is visualizing LINQ debugging and filtering collection in run-time. I have more than 5 years of hands on experience in .NET C#, mainly in client-side development. I’ve build applications from physics analytics to C&C geo-location based applications. I’m also a OzCode Evangelist and a blogger. You can check-out few blogs I’ve wrote on “How to mongoDB in C#” And that’s the end of my self promotion(it never hurts right?). So.. Let’s talk about reactive extensions… how many of you guys heard about reactive extensions?
  • #13: So want do we really want? We want to have one language which talks about all those three things.. Cause really events and callbacks… and a task returning from being completed are really all events, right? They all do the same thing. But we can’t refer to them at the same language. We need a func of something for the callback and a delegate of some sort for event, and we need to await something to be completed. I’m treating all of those unified things as a separate things and I can’t combine them. And when I can’t combine them easily.. I can’t describe how they relate.. Easily. ???So if I have a UI button that has a click event and I can’t describe how that click event is related to this async go and do google search?? Sooo… what if we try to make the most generic API which handles all of those scenarios in a unified language ?
  • #22: So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  • #23: So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  • #24: So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  • #25: So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  • #26: So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  • #27: So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  • #28: So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  • #29: So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..