2015-06-23 6 views
8

तत्काल क्योंSchedulers: बनाम CurrentThread

Observable.Return(5) 
    .Repeat() 
    .Take(1) 

कभी नहीं पूरा करता है के लिए explanation, लेकिन

Observable.Return(5, Scheduler.CurrentThread) 
    .Repeat() 
    .Take(1) 

काम करता है पढ़ने के रूप में उम्मीद के बाद। मैं अभी भी उलझन में हूं और मैं नहीं बता सकता कि क्यों currentThread वास्तव में समस्या हल करता है। क्या कोई स्पष्ट स्पष्टीकरण दे सकता है?

+0

मैंने दोनों की कोशिश की है और वे दोनों मेरे लिए ठीक है। क्या आप कोड पोस्ट कर सकते हैं जो समस्या को पुन: उत्पन्न करता है? – Enigmativity

+1

इसे देखें [पोस्ट] (https://social.msdn.microsoft.com/Forums/en-US/7f75482f-eff2-4938-9491-47fe870989e8/currentthreadscheduler-vs-immediatescheduler?forum=rx)। –

+0

@ लिनपैड में मेरे लिए पहली बार ताकतवरता, हालांकि यह –

उत्तर

4

link उपरोक्त टिप्पणियों में नेड स्टोयानोव द्वारा प्रदान की गई डेव सेक्स्टन द्वारा एक महान स्पष्टीकरण है।

मैं इसे थोड़ा अलग तरीके से चित्रित करने की कोशिश करूंगा। इस उदाहरण को लें जहां रिकर्सिवटेस्ट विधि में रिकर्सिव कॉल होता है।

public class RecursiveTest() 
{ 
    private bool _isDone; 

    public void RecursiveMethod() 
    { 
     if (!_isDone) 
     { 
      RecursiveMethod(); 

      // Never gets here... 
      _isDone = true; 
     } 
    } 
} 

आप आसानी से देख सकते हैं कि यह अनिश्चित काल के लिए recurse होगा (क StackOverflowException तक) क्योंकि _isDone सही पर सेट हो जाता है कभी नहीं होगा। यह एक अत्यधिक सरलीकृत उदाहरण है, लेकिन यह मूल रूप से आपके पहले उदाहरण के साथ क्या चल रहा है।

यह आपके पहले उदाहरण में क्या होता है इसका वर्णन करने के लिए डेव सेक्स्टन द्वारा स्पष्टीकरण है।

डिफ़ॉल्ट रूप से, वापसी OnNext (1) को कॉल करने के लिए तत्काल शेड्यूलर का उपयोग करता है तो ऑनकंपलेट()। दोहराना किसी भी समवर्तीता को पेश नहीं करता है, इसलिए यह को तत्काल लागू किया जाता है और फिर तुरंत लौटने के लिए पुनः सदस्यता लेता है। क्योंकि रिटर्न में कोई ट्रैम्पोलिन नहीं है, यह पैटर्न खुद को दोहराता है, वर्तमान थ्रेड को अनिश्चित काल तक अवरुद्ध करता है। कॉलिंग इस पर सब्सक्राइब करें कभी भी रिटर्न नहीं देता है।

दूसरे शब्दों में, पुनर्वित्त के अनंत लूप की वजह से, प्रारंभिक प्रवाह पूरी तरह से पूरा नहीं हो जाता है। तो हमें पुनर्वित्त के बिना प्रारंभिक प्रवाह को पूरा करने के लिए एक तरीका चाहिए।

चलो इस पोस्ट में उपरोक्त मेरे रिकर्सिवटेस्ट उदाहरण पर वापस जाएं, अनंत रिकर्सन से बचने का समाधान क्या होगा? रिकर्सिव विधि को फिर से निष्पादित करने से पहले हमें इसके प्रवाह को पूरा करने के लिए रिकर्सिव विधि की आवश्यकता होगी।

public void RecursiveMethod() 
{ 
    if (!_isDone) 
    { 
     Enqueue(RecursiveMethod); 
     _isDone = true; 
    } 
} 

इस तरह, पूरा होगा प्रारंभिक प्रवाह, _isDone सही पर सेट किया जाएगा और RecursiveMethod के बगल में कॉल है जब: एक तरह से यह करने के लिए एक कतार है और इस तरह RecursiveMethod करने के लिए कॉल करने के लिए है enqueue निष्पादित, अनंत पुनरावृत्ति से परहेज करने से अब कुछ भी निष्पादित नहीं होगा। और यह बहुत कुछ है जो शेड्यूलर। कंटेंट थ्रेड आपके दूसरे उदाहरण में करेगा।

देखें कि डेव सेक्सटन बताते हैं कि कैसे अपने दूसरे उदाहरण काम करता है:

यहाँ, वापसी CurrentTheadScheduler उपयोग कर रहा है OnNext (1) तो OnCompleted() कॉल करने के लिए। दोहराव किसी भी सहमति को पेश नहीं करता है, इसलिए यह को तुरंत चालू किया जाता है और फिर तुरंत वापसी के लिए सदस्यता लेता है; हालांकि, रिटर्न के लिए यह दूसरी सदस्यता ट्राम्पोलिन पर अपने (आंतरिक) क्रियाओं को शेड्यूल करती है क्योंकि यह अभी भी पर पहले से निर्धारित (बाहरी) क्रिया से पूर्ण कॉलबैक पर निष्पादित है, इस प्रकार पुनरावृत्ति तुरंत नहीं होती है।यह दोहराए जाने के लिए डिस्पोजेबल को वापस करने की अनुमति देता है, जो अंततः ऑनकंपलेट को कॉल करता है, रीपेट का निपटारा करके पुनरावृत्ति रद्द करता है, और आखिरकार सदस्यता रिटर्न से कॉल करता है।

फिर से मेरा उदाहरण वास्तव में समझने में आसान बनाने के लिए सरल था और यह बिल्कुल ठीक नहीं है। Here you can see शेड्यूलर वास्तव में कैसे काम करता है। यह उन ट्रैम्पोलिन को उपयोग करता है जो मूल रूप से एक कतार है जो सुनिश्चित करता है कि कोई पुनर्वित्त कॉल नहीं है। इसलिए सभी कॉल एक ही थ्रेड पर दूसरे के बाद क्रमबद्ध होते हैं। ऐसा करके, प्रारंभिक प्रवाह पूरा किया जा सकता है जो अनंत पुनर्विक्रेता पाश से बचाता है।

आशा है कि यह थोड़ा स्पष्ट है :)

+0

दिखाता रहता है इस उत्तर के लिए धन्यवाद, यह मेरे लिए वास्तव में स्पष्ट है। – GiantSquid

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