2012-01-18 12 views
6

मैंने ब्लॉग से ReactiveUi के उदाहरणों को देखा है और मुझे आश्चर्य है कि क्या ReactiveUI के पास कुछ प्रकार की सदस्यता प्रबंधन सुविधा है या इस तथ्य को अनदेखा करने वाले उदाहरण हैं कि वे सब्सक्रिप्शन को रिसाव कर सकते हैं?प्रतिक्रियाशील यूआई रिसाव सदस्यता करता है?

जब भी मैं ReactiveUi में कोई विधि कॉल करता हूं जिसके परिणामस्वरूप IDisposable होता है, तो क्या मुझे उस संदर्भ को पकड़ने और इसे स्वयं ट्रैक करने की आवश्यकता है? इसका मतलब यह भी है कि मेरे व्यू मॉडल्स को डिस्पोजेबल होने की आवश्यकता है, यह मुश्किल लगता है क्योंकि हम वास्तव में नहीं जानते हैं कि जब कनेक्ट किए गए "दृश्य" दूर जाते हैं (यानी यदि मेरा व्यूमोडेल डेटा ग्रिड में आइटम को प्रतिबिंबित करता है) तो ऐसा कोई उपयुक्त नहीं लगता है निपटान कॉल करने के लिए जगह।

उत्तर

10

आपको केवल IDisposable पर सब्सक्रिप्शन द्वारा लौटाए जाने की आवश्यकता है यदि आपको को अवलोकन योग्य से सदस्यता समाप्त करने की आवश्यकता है। ऑब्जर्वेबल स्वाभाविक रूप से Dispose पर कॉल करेंगे जब वे OnCompleted या OnError संदेशों को समाप्त करते हैं।

हालांकि, जब आपके पास अनंत अवलोकन योग्य सदस्यता (यानी FromEventPattern) है, तो संदर्भों को रखने की आवश्यकता है, लेकिन यह फ़ॉर्म/दृश्य को बंद करने से पहले ईवेंट हैंडलर को हटाने की आवश्यकता के समान ही है।

+0

आम तौर पर यदि प्रकाशक का जीवनकाल ग्राहक के जीवनकाल से समान या छोटा होता है तो आपको फॉर्म बंद होने पर ईवेंट हैंडलर को हटाना नहीं पड़ता है।उदाहरण के लिए ReactiveCommand पर एक ही सिद्धांत लागू होता है? – KolA

+1

@ कोला - मैं सुझाव दूंगा कि आप सभी आरएक्स सदस्यता का स्पष्ट रूप से निपटान करते हैं यदि आप जानते हैं कि कुछ अभी भी सुरक्षित होने के लिए चल रहे हैं। एक फॉर्म-लेवल 'कंपोजिट डिस्पोजेबल' होना पर्याप्त है जो आप सभी सब्सक्रिप्शन ट्रैक करते हैं। इसका अर्थ यह है कि जब आप बाहर निकलते हैं तो केवल एक ही 'डिस्प्ले()' का उपयोग करें। नियमित घटनाओं की तरह, आप ऐसा करने के बिना दूर हो सकते हैं लेकिन यह हमेशा मामला नहीं है। – Enigmativity

13

आपको यह भी याद रखना होगा कि आरएक्स और रिएक्टिवयूआई द्वारा लौटाई गई आईडीआईस्पोजेबल्स अप्रबंधित स्मृति से जुड़े नहीं हैं - यह सब कुछ सरल है। नेट ऑब्जेक्ट्स, अभी भी कचरा कलेक्टर द्वारा refeded है।

आपके प्रतिक्रियाशील ऑब्जेक्ट्स के रचनाकारों में आपके द्वारा किए गए अधिकांश सदस्यता होस्ट ऑब्जेक्ट के जीवनकाल से बंधे रहेंगे - इसलिए जब यह दायरे से बाहर हो जाती है और जीसी के अधीन होती है, तो क्या सभी सदस्यता, सीएलआर का पता लगाएगा परिपत्र संदर्भ और बस सबकुछ nuke।

जैसा कि गूढ़ता का उल्लेख है, एक मुश्किल बात यह है कि जब आप एक WPF ऑब्जेक्ट के जीवनकाल में एक सदस्यता (और शायद, एक व्यूमोडेल) के जीवनकाल को बांधने के लिए FromEventPattern का उपयोग करते हैं। हालांकि, मैं तर्क दूंगा कि यदि आप ReactiveUI में अक्सर FromEventPattern का उपयोग कर रहे हैं, तो आप निश्चित रूप से इसे गलत तरीके से कर रहे हैं।

RxUI सभी ViewModels के बारे में है, और ViewModels ताकि आप अपने दृश्यों से अलग से उपयोगकर्ता अनुभव के व्यवहार परीक्षण कर सकते हैं, के बारे में आदेशों और गुण (और तारों अप कैसे गुण एक दूसरे से जुड़े हुए हैं) सभी कर रहे हैं ।

+0

लेकिन प्रॉपर्टी चेंज और प्रॉपर्टी चेंजिंग इवेंट्स पर इवेंटपेटर्न से सिर्फ प्रॉपर्टीज और ऑब्जेक्टेड चेंज "इवेंट्स" का उपयोग नहीं कर रहा है? और निष्पादित कार्यक्रम में आने वाले कमांडों का उपयोग नहीं है? मुझे लगता है कि यह मुझे चिंता करता है। – Damian

+0

नहीं, आंतरिक रूप से प्रतिक्रियाशील ऑब्जेक्ट एक विषय का उपयोग करता है, जब आप ObservableForProperty या WhenAny –

+0

ठीक करते हैं तो आप FromEventPattern का उपयोग नहीं कर रहे हैं। स्पष्टीकरण के लिए धन्यवाद। मैं जवाब के रूप में इनिग्मैटीविटी के जवाब को चिह्नित कर रहा हूं क्योंकि वह पहले सही था, लेकिन आपके स्पष्टीकरण मेरे कन्वर्ट स्तर के लिए महत्वपूर्ण था। – Damian

2

बस सुरक्षित होने के लिए मैं इस पैटर्न का उपयोग अब से करूँगा। मैं शायद विस्तार विधियों के माध्यम से काम करने के लिए संशोधित करूँगा लेकिन सिद्धांत ध्वनि है। सुनिश्चित करें कि आप सदस्यता तो मैं मुक्त करने के लिए SizeChangedObserver() और UnloadedObserver() पाने के बजाय आप उन्हें ड्रॉप करने

class Mesh2D{ 

    public Mesh2D() 
    { 
     DisposeOnUnload(CreateBindings()); 
    } 

    // Register all disposables for disposal on 
    // UIElement.Unload event. This should be 
    // moved to an extension method. 
    void DisposeOnUnload(IEnumerable<IDisposable> disposables) 
    { 
     var d = new CompositeDisposable(disposables); 
     var d2 = this.UnloadedObserver() 
      .Subscribe(e => d.Dispose()); 
     var d3 = this.Dispatcher.ShutdownStartedObserver() 
      .Subscribe(e => d.Dispose()); 
     d.Add(d2); 
     d.Add(d3); 
    } 

    // Where your bindings are simply yielded and 
    // they are removed on Unload magically 
    IEnumerable<IDisposable> CreateBindings() 
    { 
     // When the size changes we need to update all the transforms on 
     // the markers to reposition them. 
     yield return this.SizeChangedObserver() 
      .Throttle(TimeSpan.FromMilliseconds(20), RxApp.DeferredScheduler) 
      .Subscribe(eventArgs => this.ResetImageSource()); 

     // If the points change or the viewport changes 
     yield return this.WhenAny(t => t.Mesh, t => t.Viewport, (x, t) => x.Value) 
      .Throttle(TimeSpan.FromMilliseconds(20), RxApp.DeferredScheduler) 
      .Subscribe(t => this.UpdateMeshChanged()); 
    } 
} 

नोट मैं स्वचालित रूप से उत्पन्न विस्तार के तरीकों के साथ RX FromEventPattern लपेटकर कर रहा हूँ चाहते रिसाव नहीं है होना करने के लिए FromEventPattern के प्रारूप को याद रखना मुश्किल है।

रैपिंग कोड इस तरह के

public static IObservable<EventPattern<RoutedEventArgs>> UnloadedObserver(this FrameworkElement This){ 
    return Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>(h => This.Unloaded += h, h => This.Unloaded -= h); 
} 

ऊपर पैटर्न के रूप में उत्पन्न होता है शायद IDisposable दृश्य मॉडल निकल करने के साथ ही इस्तेमाल किया जा सकता।

संबंधित मुद्दे