Rx:1-Observable
.net的IEnumerable接口是返回IEnumerator,而IEnumerator实现了MoveNext()和获取当前对象等方法。
Observable利用该思想,使用IObservable<T>和IObserver<T>实现Push-Style(推模式),我们常用的IEnumerble可以理解为拉模式或主动模式,那么就需要返回IEnumerator来操作。而推模式正好相反,所以IObserver<T>是作为IObserverable<T>的参数传进去的:
1: public interface IObservable<T>
2: {3: // Methods
4: IDisposable Subscribe(IObserver<T> observer); 5: }1: public interface IObserver<T>
2: {3: // Methods
4: void OnCompleted();
5: void OnError(Exception exception);
6: void OnNext(T value);
7: }System.Observable.dll里就只有这两个接口的定义。这个接口是定义在System命名空间下的。
Inactive和Reactive是两种思想,前者是基于状态的,后者是基于事件的。基于事件通知的好处就在于线程不用blocking去wait,所以程序的吞吐量会大大增加。换个角度,可以理解为Inactive就是主动的,Reactive就是被动的。
Reactive这种被动模式常被称作Push模式。这么看到,IObservable就是Push的“来源”(外界推力),IObserver就是“要被推到的目标”。两者通过“目标”的主动订阅(Subscribe方法)来结合,当然,“目标”是可以订阅多个“外界作用力的”。
拿一个从1加到100的例子:
1: class Program
2: {3: /// <summary>
4: /// 该方式直接使用Extension method创建匿名的Observer
5: /// </summary>
6: /// <param name="args"></param>
7: static void Main(string[] args)
8: {9: var ob1 = new Ob1();
10: ob1.Subscribe(str=>Console.WriteLine(str), ()=>Console.WriteLine("DONE!"));
11: 12: Console.WriteLine("has subscribed...");
13: ThreadPool.QueueUserWorkItem(obj => ob1.DoJob(obj));14: Console.WriteLine("has started DoJob()\n");
15: 16: Console.ReadLine(); 17: } 18: 19: /// <summary>
20: /// 这种方式需要一个Observer来相应
21: /// </summary>
22: private static void Main1()
23: {24: var theObserver = new TheObserver();
25: 26: var ob1 = new Ob1();
27: var unsubscribeHandler = ob1.Subscribe(theObserver); 28: 29: Console.WriteLine("has subscribed...");
30: ThreadPool.QueueUserWorkItem(obj => ob1.DoJob(obj));31: Console.WriteLine("has started DoJob()\n");
32: 33: Console.ReadLine(); 34: } 35: } 36: 37: public class TheObserver : IObserver<string>
38: {39: public void OnCompleted()
40: {41: Console.WriteLine("Completed");
42: } 43: 44: public void OnError(Exception exception)
45: { 46: Console.WriteLine(exception.Message); 47: } 48: 49: public void OnNext(string str)
50: { 51: Console.WriteLine(str); 52: } 53: } 54: 55: public class Ob1 : IObservable<string>
56: {57: private List<IObserver<string>> observers = new List<IObserver<string>>();
58: 59: public IDisposable Subscribe(IObserver<string> observer)
60: { 61: observers.Add(observer);62: return new Unsubscribe(observer, p => observers.Remove(p));
63: } 64: 65: public void DoJob(object obj)
66: { 67: var sum = 0;68: try
69: {70: for (int i = 0; i < 100; i++)
71: { 72: observers.ForEach(p => p.OnNext((++sum).ToString())); 73: Thread.Sleep(30); 74: } 75: }76: catch (Exception ex)
77: { 78: observers.ForEach(p=>p.OnError(ex)); 79: } 80: 81: observers.ForEach(p=>p.OnCompleted()); 82: } 83: } 84: 85: public class Unsubscribe : IDisposable
86: {87: public IObserver<string> Source { get; set; }
88: public Action<IObserver<string>> DisposeAction { get; set; }
89: 90: public Unsubscribe(IObserver<string> source, Action<IObserver<string>> disposeAction)
91: {92: this.Source = source;
93: this.DisposeAction = disposeAction;
94: } 95: 96: public void Dispose()
97: { 98: DisposeAction(Source); 99: } 100: }在System.Reactive.dll里为IObservable<T>提供了如下的扩展方法:
1: public static class ObservableExtensions
2: {3: // Methods
4: public static IDisposable Subscribe<TSource>(this IObservable<TSource> source);
5: public static IDisposable Subscribe<TSource>(this IObservable<TSource> source, Action<TSource> onNext);
6: public static IDisposable Subscribe<TSource>(this IObservable<TSource> source, Action<TSource> onNext, Action<Exception> onError);
7: public static IDisposable Subscribe<TSource>(this IObservable<TSource> source, Action<TSource> onNext, Action onCompleted);
8: public static IDisposable Subscribe<TSource>(this IObservable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted);
9: } 10: 11: 所以我们更简单的写了:
1: static void Main(string[] args)
2: { 3: var observables = Observable.Interval(TimeSpan.FromMilliseconds(30)).TakeWhile(p => p <= 100); 4: var newObservable = observables.Select(p => --p); 5: observables.Subscribe(p => Console.WriteLine(p));6: newObservable.Subscribe(c => Console.WriteLine("\t" + c));
7: Thread.Sleep(3000);8: Console.WriteLine("start");
9: Console.ReadLine(); 10: }这里Line 5的Select方法会在每次生成observables的OnNext的时候调用一次。
浙公网安备 33010602011771号