Skip to content

Commit 6dfed82

Browse files
authored
Update IntroToRx for Rx 6.1 (#2242)
* Document ResetExceptionDispatchState * Add official documentation for the hitherto undocumented rules around reuse of exception objects, and also updates the docs for the various operators whose use might create a scenario where you need this new operator. * Add TakeUntil(Cancellation) docs * Add DisposeWith documentation * Update Foreword to refer to 6.1 * Add edition history to foreword
1 parent 1ffbcad commit 6dfed82

File tree

7 files changed

+234
-6
lines changed

7 files changed

+234
-6
lines changed

Rx.NET/Documentation/IntroToRx/00_Foreword.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,27 @@ Thanks also to those who continued to work on Rx.NET after it ceased to be direc
4747

4848
If you are interested in more information about the origins of Rx, you might find the [A Little History of Reaqtor](https://reaqtive.net/) ebook illuminating.
4949

50-
The version that this book has been written against is `System.Reactive` version 6.0. The source for this book can be found at [https://github.com/dotnet/reactive/tree/main/Rx.NET/Documentation/IntroToRx](https://github.com/dotnet/reactive/tree/main/Rx.NET/Documentation/IntroToRx). If you find any bugs or other issues in this book, please [create an issue](https://github.com/dotnet/reactive/issues) at https://github.com/dotnet/reactive/. You might find the [Reactive X slack](reactivex.slack.com) to be a useful resource if you start using Rx.NET in earnest.
50+
The version that this book has been written against is `System.Reactive` version 6.1. The source for this book can be found at [https://github.com/dotnet/reactive/tree/main/Rx.NET/Documentation/IntroToRx](https://github.com/dotnet/reactive/tree/main/Rx.NET/Documentation/IntroToRx). If you find any bugs or other issues in this book, please [create an issue](https://github.com/dotnet/reactive/issues) at https://github.com/dotnet/reactive/. You might find the [Reactive X slack](reactivex.slack.com) to be a useful resource if you start using Rx.NET in earnest.
5151

5252
So, fire up Visual Studio and let's get started.
5353

54+
# Edition History
55+
56+
## 1st edition
57+
58+
The original book written by Lee Campbell.
59+
60+
## 2nd edition
61+
62+
Updated and revised by Ian Griffiths to align with the Rx v6.0 release.
63+
64+
## 3rd edition
65+
66+
Updates for Rx v6.1:
67+
68+
* Documented new `TakeUntil(CancellationToken)` overload
69+
* Documented new `DiposeWith` extension method for `IDisposable`
70+
* Documented new `ResetExceptionDispatchState` operator
71+
* Added guidance to clarify rules around reusing exception objects in scenarios where Rx will rethrow them
72+
5473
---

Rx.NET/Documentation/IntroToRx/03_CreatingObservableSequences.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,9 @@ As an example of where you might want to use `Never` for timing purposes, suppos
381381
IObservable<string> throws = Observable.Throw<string>(new Exception());
382382
```
383383

384+
Be aware that this if you use this operator in conjunction with any of the mechanisms described in the [Leaving Rx's World](13_LeavingIObservable.md) chapter, you might fall foul of the rules described in [Exception state](13_LeavingIObservable.md#exception-state). If you need to use `await` (or similar mechanisms that will turn a call to `OnError` into a rethrow) you may need to use the [`ResetExceptionDispatchState`](13_LeavingIObservable.md#resetexceptiondispatchstate) operator to ensure that each rethrowing of the exception gets suitably reset exception state. (This problem only arises if you cause the same exception to be rethrown multiple times.)
385+
386+
384387
### Observable.Create
385388

386389
The `Create` factory method is more powerful than the other creation methods because it can be used to create any kind of sequence. You could implement any of the preceding four methods with `Observable.Create`.
@@ -516,7 +519,7 @@ public static IObservable<T> Never<T>()
516519
});
517520
}
518521

519-
public static IObservable<T> Throws<T>(Exception exception)
522+
public static IObservable<T> Throw<T>(Exception exception)
520523
{
521524
return Observable.Create<T>(o =>
522525
{
@@ -1201,6 +1204,9 @@ Sub2: 4
12011204

12021205
Alternatively, you can specify a time-based limit by passing a `TimeSpan` to the `ReplaySubject<T>` constructor.
12031206

1207+
Note that if the source reports an error (by calling `OnError`), `ReplaySubject<T>` will retain the `Exception`, and provide it to all current subscribers, and also any subsequent subscribers. This should not be a surprise—this subject's job is to replay what the source did—but be aware that this can cause a problem if you use any of the mechanisms described in the [Leaving Rx's World](13_LeavingIObservable.md) chapter. For example if you `await` an observable that uses a `ReplaySubject<T>` and if the underlying source reported an error, you will no longer be conforming to the rules described in [Exception state](13_LeavingIObservable.md#exception-state). If you need to use `await` (or similar mechanisms that will turn a call to `OnError` into a rethrow) you may need to use the [`ResetExceptionDispatchState`](13_LeavingIObservable.md#resetexceptiondispatchstate) operator to ensure that each rethrowing of the exception gets suitably reset exception state.
1208+
1209+
12041210
## `BehaviorSubject<T>`
12051211

12061212
Like `ReplaySubject<T>`, `BehaviorSubject<T>` also has a memory, but it remembers exactly one value. However, it's not quite the same as a `ReplaySubject<T>` with a buffer size of 1. Whereas a `ReplaySubject<T>` starts off in a state where it has nothing in its memory, `BehaviorSubject<T>` always remembers _exactly_ one item. How can that work before we've made our first call to `OnNext`? `BehaviorSubject<T>` enforces this by requiring us to supply the initial value when we construct it.

Rx.NET/Documentation/IntroToRx/05_Filtering.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,8 @@ We don't have to use a time, `TakeUntil` offers an overload that accept a second
383383

384384
**Note**: these overloads require the second observable to produce a value in order to trigger the start or end. If that second observable completes without producing a single notification, then it has no effect—`TakeUntil` will continue to take items indefinitely; `SkipUntil` will never produce anything. In other words, these operators would treat `Observable.Empty<T>()` as being effectively equivalent to `Observable.Never<T>()`.
385385

386+
There is also an overload of `TakeUntil` that accepts a `CancellationToken`. This forwards notifications from the source until either the source itself completes, or the token signals cancellation, at which point `TakeUntil` will complete.
387+
386388
### Distinct and DistinctUntilChanged
387389

388390
`Distinct` is yet another standard LINQ operator. It removes duplicates from a sequence. To do this, it needs to remember all the values that its source has ever produced, so that it can filter out any items that it has seen before. Rx includes an implementation of `Distinct`, and this example uses it to display the unique identifier of vessels generating AIS messages, but ensuring that we only display each such identifier the first time we see it:

0 commit comments

Comments
 (0)