2012-02-06 9 views
10

मैं कुछ आरएक्स का उपयोग कर कोड है, एक से अधिक थ्रेड से कहा जाता है कि करता है का उपयोग कर OnNext Rx में कॉल:बचना ओवरलैपिंग जब SubscribeOn (Scheduler.TaskPool)

subject.OnNext(value); // where subject is Subject<T> 

मैं चाहता हूँ मूल्यों पृष्ठभूमि में प्रोसेस किया है, इसलिए मेरी सदस्यता

subscription = subject.ObserveOn(Scheduler.TaskPool).Subscribe(value => 
{ 
    // use value 
}); 

मैं वास्तव में परवाह नहीं है जो धागे नमूदार से बाहर आने के मानों का प्रबंधन, जब तक काम TaskPool में डाल दिया है और मौजूदा धागा ब्लॉक नहीं करता है। हालांकि, मेरे ऑननेक्स्ट प्रतिनिधि के अंदर 'मूल्य' का उपयोग थ्रेड सुरक्षित नहीं है। फिलहाल, अगर अवलोकन के माध्यम से बहुत सारे मूल्य चल रहे हैं तो मुझे अपने ऑननेक्स्ट हैंडलर को ओवरलैपिंग कॉल मिल रही हैं।

मैं अपने ऑननेक्स्ट प्रतिनिधि को केवल एक लॉक जोड़ सकता हूं, लेकिन यह चीजों को करने का आरएक्स तरीका नहीं लगता है। यह सुनिश्चित करने का सबसे अच्छा तरीका क्या है कि मेरे पास केवल एक ही समय में मेरे ऑननेक्स्ट हैंडलर को एक कॉल है, जब मेरे पास subject.OnNext(value); पर कॉल करने वाले एकाधिक थ्रेड हैं?

उत्तर

10
MSDN

पर

Using Subjects से डिफ़ॉल्ट रूप से, विषयों धागे भर में किसी भी तुल्यकालन प्रदर्शन नहीं करते। [...] यदि, हालांकि, आप शेड्यूलर का उपयोग करके पर्यवेक्षकों को आउटगोइंग कॉल सिंक्रनाइज़ करना चाहते हैं, तो आप ऐसा करने के लिए सिंक्रनाइज़ विधि का उपयोग कर सकते हैं।

तो ब्रैंडन टिप्पणियों में कहता है कि आपको इस विषय को सिंक्रनाइज़ करना चाहिए और अपने निर्माता धागे को सौंपना चाहिए। जैसे

var syncSubject = Subject.Synchronize(subject); 

// syncSubject.OnNext(value) can be used from multiple threads 

subscription = syncSubject.ObserveOn(TaskPoolScheduler.Default).Subscribe(value => 
{ 
    // use value 
}); 
+2

'सिंक्रनाइज़' करने के लिए कॉल 'ObserveOn' पर कॉल से पहले होना चाहिए अन्यथा आप 'ObserveOn' के लिए समवर्ती अनुबंध का उल्लंघन कर रहे हैं। लेकिन हकीकत में यदि उपयोग का मामला कई धागे के बीच एक विषय साझा कर रहा है, तो सबसे अच्छा समाधान विषय को सिंक्रनाइज़ करने के बजाय विषय को सिंक्रनाइज़ करना है: 'var syncSubject = Subject.Synchronize (syncSubject); 'अब' syncSubject 'को हाथ दें आपके निर्माता धागे के लिए और वे मूल विषय के ग्राहकों के साथ समस्याएं पैदा किए बिना 'syncSubject.OnNext()' को कॉल कर सकते हैं। – Brandon

+0

@ ब्रैंडन var syncSubject = विषय.Synchronize (syncSubject); ... आप इसे आवंटित करने से पहले एक चर का उपयोग कर रहे हैं, क्या आप इसे स्पष्ट कर सकते हैं? – Beachwalker

+0

@ बेचवाल्कर जो एक टाइपो है।उत्तर में दिखाए गए अनुसार सिंक्रनाइज़ करने के लिए तर्क के रूप में इसे 'विषय' होना चाहिए – Brandon

-3

आप अपने स्वयं के IObserver को लागू करने का प्रयास कर सकते हैं जो इसकी ऑनएक्स्ट विधि में लॉक लागू करेगा। बस एक साधारण सजावट: लॉक लागू करें, आंतरिक ऑननेक्स्ट पर कॉल करें, लॉक को हटा दें।

फिर आप IObservable पर एक एक्सटेंशन विधि को कार्यान्वित कर सकते हैं, जैसे कुछ। थ्रेडसेफ()।

+1

सबसे अच्छा समाधान नहीं है लेकिन मेरे दृष्टिकोण से डाउनवॉटेड होने की आवश्यकता नहीं है क्योंकि यह एक वैध समाधान है। तो यहां से डाउनवॉट्स के साथ थोड़ा सा संतुलन करने के लिए मुझे +1 करें। – Beachwalker

5

मुझे लगता है कि आप सिंक्रनाइज़() एक्सटेंशन विधि की तलाश में हैं। हालिया रिलीज (2011 के उत्तरार्ध में) में प्रदर्शन सुधार प्राप्त करने के लिए वे आरएक्स टीम ने अवलोकन अनुक्रम उत्पादकों की अनुक्रमिक प्रकृति के बारे में धारणाओं को आराम दिया। हालांकि ऐसा लगता है कि आप इन मान्यताओं को तोड़ते हैं (बुरी चीज नहीं) लेकिन आरएक्स को वापस खेलने के लिए उपयोगकर्ताओं की अपेक्षा करने के लिए, आपको अनुक्रम को सिंक्रनाइज़ करना चाहिए ताकि यह सुनिश्चित हो सके कि यह अनुक्रमिक है।

1

यहां कुछ और स्पष्टीकरण Synchronize (दूसरा अनुच्छेद) का उपयोग क्यों करें। दूसरी तरफ सिंक्रनाइज़ डेडलॉक में भाग ले सकता है यदि आप सक्रिय रूप से अपने कोड में लॉकिंग का उपयोग करते हैं, कम से कम मैंने ऐसी स्थिति देखी है।

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