2011-11-10 6 views
5

हम अपने चांदी के आवेदन के भीतर गतिविधि की निगरानी के लिए आरएक्स का उपयोग कर रहे हैं ताकि हम निष्क्रियता की अवधि के बाद उपयोगकर्ता को एक संदेश प्रदर्शित कर सकें।सदस्यता के बाद एक अवलोकन अनुक्रम जोड़ना

हम घटनाओं (माउस चाल आदि) को अवलोकन में बदल रहे हैं और फिर एक एकल (सभी सक्रियता) देखने योग्य बनाने के लिए अवलोकनों को एक साथ विलय कर रहे हैं। फिर हम एक समय-समय पर उपयोग की जाने वाली सभी सक्रियता को थ्रॉटल करते हैं और कुछ समय के लिए सिस्टम निष्क्रिय होने पर अधिसूचित होने की सदस्यता लेती है।

सदस्यता के बाद मैं इसे एक नया अवलोकन/अनुक्रम कैसे जोड़ सकता हूं (ताकि सब्सक्रिप्शन बिना सदस्यता रद्द और पुनः सदस्यता के इसे उठाए)।

उदा। कई अनुक्रमों को एक साथ मिलाएं, थ्रॉटल करें, सब्सक्राइब करें। अब पर्यवेक्षित के लिए एक अतिरिक्त अनुक्रम जोड़ें जो सब्सक्राइब किया गया है।

उदाहरण कोड:

private IObservable<DateTime> allActivity; 
public void CreateActivityObservables(UIElement uiElement) 
{ 
    // Create IObservables of event types we are interested in and project them as DateTimes 
    // These are our observables sequences that can push data to subscribers/ observers 
    // NB: These are like IQueryables in the sense that they do not iterate over the sequence just provide an IObservable type 
    var mouseMoveActivity = Observable.FromEventPattern<MouseEventHandler, MouseEventArgs>(h => uiElement.MouseMove += h, h => uiElement.MouseMove -= h) 
             .Select(o => DateTime.Now); 

    var mouseLeftButtonActivity = Observable.FromEventPattern<MouseButtonEventHandler, MouseButtonEventArgs>(h => uiElement.MouseLeftButtonDown += h, h => uiElement.MouseLeftButtonDown -= h) 
              .Select(o => DateTime.Now); 

    var mouseRightButtonActivity = Observable.FromEventPattern<MouseButtonEventHandler, MouseButtonEventArgs>(h => uiElement.MouseRightButtonDown += h, h => uiElement.MouseRightButtonDown -= h) 
              .Select(o => DateTime.Now); 

    var mouseWheelActivity = Observable.FromEventPattern<MouseWheelEventHandler, MouseWheelEventArgs>(h => uiElement.MouseWheel += h, h => uiElement.MouseWheel -= h) 
             .Select(o => DateTime.Now); 

    var keyboardActivity = Observable.FromEventPattern<KeyEventHandler, KeyEventArgs>(h => uiElement.KeyDown += h, h => uiElement.KeyDown -= h) 
            .Select(o => DateTime.Now); 

    var streetViewContainer = HtmlPage.Document.GetElementById("streetViewContainer"); 
     var mouseMoveHandler = new EventHandler<HtmlEventArgs>(this.Moo); 
     bool b = streetViewContainer.AttachEvent("mousemove", mouseMoveHandler); 

    var browserActivity = Observable.FromEventPattern<Landmark.QDesk.ApplicationServices.IdleTimeoutService.MouseMoveHandler, HtmlEventArgs>(h => this.MyMouseMove += h, h => this.MyMouseMove -= h).Select(o => DateTime.Now); 

    // Merge the IObservables<DateTime> together into one stream/ sequence 
    this.allActivity = mouseMoveActivity.Merge(mouseLeftButtonActivity) 
             .Merge(mouseRightButtonActivity) 
             .Merge(mouseWheelActivity) 
             .Merge(keyboardActivity) 
             .Merge(browserActivity); 
} 

public IDisposable Subscribe(TimeSpan timeSpan, Action<DateTime> timeoutAction) 
{ 
    IObservable<DateTime> timeoutNotification = this.allActivity.Merge (IdleTimeoutService.GetDateTimeNowObservable()) 
                   .Throttle(timeSpan) 
                    .ObserveOn(Scheduler.ThreadPool); 

    return timeoutNotification.Subscribe(timeoutAction); 
} 

उत्तर

5

सबसे आसान यह करने के लिए Merge कॉल के स्थान पर एक मध्यवर्ती विषय का उपयोग करने के होगा जिस तरह से।

Subject<DateTime> allActivities = new Subject<DateTime>(); 
var activitySubscriptions = new CompositeDisposable(); 

activitySubscriptions.Add(mouseMoveActivity.Subscribe(allActivities)); 
activitySubscriptions.Add(mouseLeftButtonActivity.Subscribe(allActivities)); 
//etc ... 

//subscribe to activities 
allActivities.Throttle(timeSpan) 
      .Subscribe(timeoutAction); 

//later add another 
activitySubscriptions.Add(newActivity.Subscribe(allActivities)); 

Subject वर्ग observables यह अगर यह किसी भी OnError या OnCompleted प्राप्त करता है की सदस्यता दी गई में से किसी से OnNext (और आगे OnError और OnCompleted) घटनाओं गुजर बंद हो जाएगा।

इस दृष्टिकोण और आपके नमूने के बीच मुख्य अंतर यह है कि जब आप मर्ज किए गए अवलोकन योग्य की सदस्यता लेते हैं, तो यह विषय की सभी घटनाओं की सदस्यता लेता है। चूंकि आपके उदाहरण में सभी अवलोकन योग्य हैं, अंतर ध्यान देने योग्य नहीं होना चाहिए।

+0

हाय गिडियन, इसके लिए धन्यवाद। आपका उत्तर, किसी विषय का उपयोग करके, निम्नलिखित फोरम पर डेव सेक्स्टन द्वारा प्रदान किए गए उत्तर के समान है (मैंने डेव के समाधान का परीक्षण किया है और ऐसा लगता है कि यह बहुत अच्छी तरह से काम करता है): http://social.msdn.microsoft.com/Forums/is/rx/thread/a896d6ff-0cf3-44c9-bbaa-02ab256e21b3 – user1040208

+0

@ user1040208 एक अंतर मैं देखता हूं कि डेव के संस्करण में प्रत्येक पर्यवेक्षक के लिए स्रोत अवलोकनों की सदस्यता होगी, जहां मेरा केवल एक (विषय) परवाह होगा पर्यवेक्षकों की संख्या का। इस उपयोग के लिए, इससे कोई फर्क नहीं पड़ता है, लेकिन यह ध्यान देने योग्य है कि इस दृष्टिकोण का उपयोग कहीं और किया जाता है। –

16

मर्ज करने के लिए है कि एक IObservable < IObservable <TSource> > में ले जाता है एक अधिभार नहीं है। बाहरी अनुक्रम को एक विषय < IObservable <TSource> > बनाएं और जब आप गुच्छा में कोई अन्य स्रोत जोड़ना चाहते हैं तो उस पर ऑननेक्स्ट को कॉल करें। मर्ज ऑपरेटर को स्रोत प्राप्त होगा और इसकी सदस्यता लें:

var xss = new Subject<IObservable<int>>(); 
xss.Merge().Subscribe(x => Console.WriteLine(x)); 

xss.OnNext(Observable.Interval(TimeSpan.FromSeconds(1.0)).Select(x => 23 + 8 * (int)x)); 
xss.OnNext(Observable.Interval(TimeSpan.FromSeconds(0.8)).Select(x => 17 + 3 * (int)x)); 
xss.OnNext(Observable.Interval(TimeSpan.FromSeconds(1.3)).Select(x => 31 + 2 * (int)x)); 
... 
+1

यहां पर आप सवालों के जवाब देने के लिए वास्तव में महान हैं। अधिक के लिए तत्पर हैं। –