@@ -15,6 +15,66 @@ namespace System.Reactive
1515 /// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
1616 public abstract class EventPatternSourceBase < TSender , TEventArgs >
1717 {
18+ private sealed class Observer : ObserverBase < EventPattern < TSender , TEventArgs > > , ISafeObserver < EventPattern < TSender , TEventArgs > >
19+ {
20+ private bool _isDone ;
21+ private bool _isAdded ;
22+ private readonly Delegate _handler ;
23+ private readonly object _gate = new object ( ) ;
24+ private readonly Action < TSender , TEventArgs > _invoke ;
25+ private readonly EventPatternSourceBase < TSender , TEventArgs > _sourceBase ;
26+
27+ public Observer ( EventPatternSourceBase < TSender , TEventArgs > sourceBase , Delegate handler , Action < TSender , TEventArgs > invoke )
28+ {
29+ _handler = handler ;
30+ _invoke = invoke ;
31+ _sourceBase = sourceBase ;
32+ }
33+
34+ protected override void OnNextCore ( EventPattern < TSender , TEventArgs > value )
35+ {
36+ _sourceBase . _invokeHandler ( _invoke , value ) ;
37+ }
38+
39+ protected override void OnErrorCore ( Exception error )
40+ {
41+ Remove ( ) ;
42+ error . Throw ( ) ;
43+ }
44+
45+ protected override void OnCompletedCore ( )
46+ {
47+ Remove ( ) ;
48+ }
49+
50+ private void Remove ( )
51+ {
52+ lock ( _gate )
53+ {
54+ if ( _isAdded )
55+ {
56+ _sourceBase . Remove ( _handler ) ;
57+ }
58+ else
59+ {
60+ _isDone = true ;
61+ }
62+ }
63+ }
64+
65+ public void SetResource ( IDisposable resource )
66+ {
67+ lock ( _gate )
68+ {
69+ if ( ! _isDone )
70+ {
71+ _sourceBase . Add ( _handler , resource ) ;
72+ _isAdded = true ;
73+ }
74+ }
75+ }
76+ }
77+
1878 private readonly IObservable < EventPattern < TSender , TEventArgs > > _source ;
1979 private readonly Dictionary < Delegate , Stack < IDisposable > > _subscriptions ;
2080 private readonly Action < Action < TSender , TEventArgs > , /*object,*/ EventPattern < TSender , TEventArgs > > _invokeHandler ;
@@ -50,42 +110,11 @@ protected void Add(Delegate handler, Action<TSender, TEventArgs> invoke)
50110 throw new ArgumentNullException ( nameof ( invoke ) ) ;
51111 }
52112
53- var gate = new object ( ) ;
54- var isAdded = false ;
55- var isDone = false ;
56-
57- var remove = new Action ( ( ) =>
58- {
59- lock ( gate )
60- {
61- if ( isAdded )
62- {
63- Remove ( handler ) ;
64- }
65- else
66- {
67- isDone = true ;
68- }
69- }
70- } ) ;
71-
113+ var observer = new Observer ( this , handler , invoke ) ;
72114 //
73115 // [OK] Use of unsafe Subscribe: non-pretentious wrapper of an observable in an event; exceptions can occur during +=.
74116 //
75- var d = _source . Subscribe /*Unsafe*/ (
76- x => _invokeHandler ( invoke , /*this,*/ x ) ,
77- ex => { remove ( ) ; ex . Throw ( ) ; } ,
78- remove
79- ) ;
80-
81- lock ( gate )
82- {
83- if ( ! isDone )
84- {
85- Add ( handler , d ) ;
86- isAdded = true ;
87- }
88- }
117+ observer . SetResource ( _source . Subscribe ( observer ) ) ;
89118 }
90119
91120 private void Add ( Delegate handler , IDisposable disposable )
0 commit comments