IObservable的两个扩展,主要用来和C# 5.0中的异步操作配合使用的。
1 static class ObservableExtend
2 {
3 public static IDisposable Subscribe<T>(this IObservable<T> stream, Action<T, CancellationToken> onNext)
4 {
5 CancellationTokenSource cts = new CancellationTokenSource();
6 return stream.Subscribe(i =>
7 {
8 cts.Cancel() ;
9 cts = new CancellationTokenSource();
10
11 try { onNext(i, cts.Token); }
12 catch { }
13 });
14 }
15
16 #region IAsyncEnumerator
17 public interface IAsyncEnumerator<T>
18 {
19 Task<bool> MoveNext();
20 T Current { get; }
21 }
22
23 class AsyncEnumerator<T> : IAsyncEnumerator<T>
24 {
25
26 TaskCompletionSource<bool> tcs;
27 IObservable<T> stream;
28
29 public AsyncEnumerator(IObservable<T> stream)
30 {
31 this.stream = stream;
32 this.tcs = new TaskCompletionSource<bool>();
33
34 stream.Subscribe(
35 item =>
36 {
37 var tcs = this.tcs;
38 this.tcs = new TaskCompletionSource<bool>();
39 this.Current = item;
40 tcs.SetResult(true);
41 },
42 err => tcs.SetException(err),
43 () => tcs.SetResult(false));
44 }
45
46 public Task<bool> MoveNext()
47 {
48 return tcs.Task;
49 }
50
51 public T Current { get; private set; }
52 }
53 #endregion
54
55 //该方法不适用于类似Observable.Range()那样在Subscribe()函数中同步主动推送数据的IObservable。
56 public static IAsyncEnumerator<T> ToAsyncEnumerable<T>(this IObservable<T> stream)
57 {
58 return new AsyncEnumerator<T>(stream);
59 }
60 }
2 {
3 public static IDisposable Subscribe<T>(this IObservable<T> stream, Action<T, CancellationToken> onNext)
4 {
5 CancellationTokenSource cts = new CancellationTokenSource();
6 return stream.Subscribe(i =>
7 {
8 cts.Cancel() ;
9 cts = new CancellationTokenSource();
10
11 try { onNext(i, cts.Token); }
12 catch { }
13 });
14 }
15
16 #region IAsyncEnumerator
17 public interface IAsyncEnumerator<T>
18 {
19 Task<bool> MoveNext();
20 T Current { get; }
21 }
22
23 class AsyncEnumerator<T> : IAsyncEnumerator<T>
24 {
25
26 TaskCompletionSource<bool> tcs;
27 IObservable<T> stream;
28
29 public AsyncEnumerator(IObservable<T> stream)
30 {
31 this.stream = stream;
32 this.tcs = new TaskCompletionSource<bool>();
33
34 stream.Subscribe(
35 item =>
36 {
37 var tcs = this.tcs;
38 this.tcs = new TaskCompletionSource<bool>();
39 this.Current = item;
40 tcs.SetResult(true);
41 },
42 err => tcs.SetException(err),
43 () => tcs.SetResult(false));
44 }
45
46 public Task<bool> MoveNext()
47 {
48 return tcs.Task;
49 }
50
51 public T Current { get; private set; }
52 }
53 #endregion
54
55 //该方法不适用于类似Observable.Range()那样在Subscribe()函数中同步主动推送数据的IObservable。
56 public static IAsyncEnumerator<T> ToAsyncEnumerable<T>(this IObservable<T> stream)
57 {
58 return new AsyncEnumerator<T>(stream);
59 }
60 }
为了简单,下面举的例子不是很典型,将就看了。
1 var stream = Observable.Interval(TimeSpan.FromSeconds(1)).Take(10);
2
3 stream.Subscribe((item, cancel) =>
4 {
5 if (cancel.IsCancellationRequested)
6 return;
7 Console.WriteLine("### " + item);
8 });
9
10 stream.Subscribe(Console.WriteLine);
11
12 TaskEx.Run(async () =>
13 {
14 var enumerator = stream.ToAsyncEnumerable();
15 while (await enumerator.MoveNext())
16 {
17 Console.WriteLine(">>> " + enumerator.Current);
18 }
19 Console.WriteLine("finished");
20 });
2
3 stream.Subscribe((item, cancel) =>
4 {
5 if (cancel.IsCancellationRequested)
6 return;
7 Console.WriteLine("### " + item);
8 });
9
10 stream.Subscribe(Console.WriteLine);
11
12 TaskEx.Run(async () =>
13 {
14 var enumerator = stream.ToAsyncEnumerable();
15 while (await enumerator.MoveNext())
16 {
17 Console.WriteLine(">>> " + enumerator.Current);
18 }
19 Console.WriteLine("finished");
20 });
