2009-12-21 18 views
18

मैं नेट पर नए समानांतर ढेर के संदर्भ में BlockingCollection का उद्देश्य समझने की कोशिश कर रहा 4.क्या BlockingCollection (टी के) का उद्देश्य है

MSDN प्रलेखन कहते हैं:

ब्लॉकिंग कोलेक्शन को एक आईपॉडसरकंसमेरकॉलेक्शन इंस्टेंस के लिए रैपर के रूप में उपयोग किया जाता है, जिससे संग्रह को हटाने के लिए डेटा को तब तक अवरुद्ध करने की अनुमति मिलती है जब तक डेटा को निकालने के लिए उपलब्ध नहीं होता है। इसी प्रकार, IProducerConsumerCollection में अनुमत डेटा तत्वों की संख्या पर ऊपरी-बाध्य को लागू करने के लिए अवरोधक चयन किया जा सकता है; संग्रह के अतिरिक्त प्रयास तब तक अवरुद्ध हो सकते हैं जब तक अतिरिक्त आइटम स्टोर करने के लिए स्थान उपलब्ध न हो।

लेकिन जब मैं कुछ IProducerConsumerCollection के कार्यान्वयन को देखो, ConcurrentQueue की तरह मुझे लगता है कि वे एक ताला मुक्त, सुरक्षित धागा, कार्यान्वयन प्रदान करते हैं। तो ब्लॉकिंग कोलेक्शन प्रदान करने वाले लॉक तंत्र की आवश्यकता क्यों है? एमएसडीएन में सभी उदाहरण ब्लॉकिंग कोलेक्शन रैपर के माध्यम से उन संग्रहों का उपयोग करते हुए दिखाते हैं, उन संग्रहों का उपयोग करने की क्या समस्याएं हैं? ब्लॉकिंग कोलेक्शन का उपयोग करके क्या लाभ पैदा करता है?

उत्तर

17

ऑपरेशन किए जाने तक अवरुद्ध करना एक सुविधा है यदि आपके पास वैसे भी करने के लिए कुछ और नहीं है (या इसके बजाय: ऑपरेशन पूरा होने तक आगे नहीं बढ़ सकता है)।

यदि आपके पास एक गैर-अवरुद्ध कतार है जिसमें से आप डेटा पढ़ना चाहते हैं, और इस समय कोई डेटा नहीं है, तो आपको समय-समय पर मतदान करना होगा, या डेटा होने तक कुछ सेमफोर पर प्रतीक्षा करना होगा। यदि कतार ब्लॉक, जो पहले से ही स्वचालित रूप से किया गया है।

इसी प्रकार, यदि आप एक गैर-अवरुद्ध कतार में पूर्ण करने की कोशिश करते हैं, तो ऑपरेशन बस असफल हो जाएगा, और फिर आपको यह पता लगाना होगा कि क्या करना है। अवरुद्ध कतार बस अंतरिक्ष होने तक प्रतीक्षा करेगी।

यदि आपके पास प्रतीक्षा करने के बजाय कुछ चालाक है (जैसे डेटा के लिए एक और कतार की जांच करना, या क्यूईटूफुल अपवाद उठाना) तो आप गैर-अवरुद्ध कतार चाहते हैं, लेकिन अक्सर ऐसा नहीं होता है।

अक्सर, कतारों को अवरुद्ध करने पर एक टाइमआउट निर्दिष्ट करने का एक तरीका है।

+0

मुझे कहीं भी नहीं मिल रहा है - "अवरुद्ध" का अर्थ क्या है, क्या यह "प्रतीक्षा" करने के बजाय "अनदेखा" कर रहा है? – Fulproof

+0

"अवरुद्ध" का अर्थ है "ऑपरेशन पूरा होने तक प्रतीक्षा करें" – Thilo

7

लॉकिंग का उद्देश्य लॉकिंग स्वयं है। आपके पास संग्रह से कई धागे पढ़ सकते हैं, और यदि कोई डेटा उपलब्ध नहीं है तो थ्रेड तब तक लॉक रहेगा जब तक कि नया डेटा न आए।

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

इस तरह आप किसी भी जांच के बिना डेटा के थ्रूपुट को थ्रॉटल करने के लिए संग्रह का उपयोग कर सकते हैं। आपके थ्रेड बस वे सब कुछ पढ़ और लिख सकते हैं, और संग्रह आवश्यक थ्रेड को काम करने या सोते रखने का ख्याल रखता है।

+3

महत्वपूर्ण हिस्सा "स्वयं को जांचने के बिना" है। आपके निर्माता और उपभोक्ता कोड दोनों वास्तव में सरल हो सकते हैं, लगभग पूरी तरह से आपके गैर-समानांतर संस्करण के समान ही हैं और फिर भी यदि आप उनके लिए कुछ भी करने के लिए उपयोगी नहीं हैं तो भी आपको सोने के धागे का लाभ मिल रहा है। – VolkerK

4

यह उन चीजों में से एक है जो इसे करने के बाद समझना बहुत आसान है।

निर्माता उपभोक्ता के लिए, दो वस्तुओं, निर्माता और उपभोक्ता हैं। वे दोनों एक कतार साझा करते हैं जो उन्हें बनाए जाने पर दिया जाता है, इसलिए वे इसके बीच लिख सकते हैं।

एक निर्माता उपभोक्ता में जोड़ा जा रहा है बहुत परिचित है, बस CompleteAdding थोड़ा अलग साथ:

public class Producer{ 
     private BlockingCollection<string> _queue; 
     public Producer(BlockingCollection<string> queue){_queue = queue;} 

     //a method to do something 
     public MakeStuff() 
     { 
      for(var i=0;i<Int.MaxValue;i++) 
      { 
       _queue.Add("a string!"); 
      } 

      _queue.CompleteAdding(); 
     } 
} 

उपभोक्ता समझ बनाने के लिए नहीं लगता है - जब तक आप महसूस करते हैं कि जब तक foreach पाशन बंद नहीं होगा कतार जोड़ना पूरा हो गया है। तब तक, यदि कोई वस्तु नहीं है, तो यह सिर्फ सोने के लिए वापस जायेगी। और चूंकि यह निर्माता और उपभोक्ता में संग्रह का एक ही उदाहरण है, इसलिए आप उपभोक्ता को केवल चक्र उठाने के लिए चक्र ले सकते हैं, और इसे रोकने, इसे पुनरारंभ करने, आदि के बारे में चिंता करने की ज़रूरत नहीं है।

public class Consumer() 
{ 
     private BlockingCollection<string> _queue; 
     public Consumer(BlockingCollection<string> queue) 
     { 
      _queue = queue; 
     } 

     public void WriteStuffToFile() 
     { 
      //we'll hold until our queue is done. If we get stuff in the queue, we'll start processing it then 
      foreach(var s in _queue.GetConsumingEnumerable()) 
      { 
      WriteToFile(s); 
      } 
     } 
} 

तो आप संग्रह का उपयोग करके उन्हें एक साथ तारते हैं।

var queue = new BlockingCollection<string>(); 
var producer = new Producer(queue); 
var consumer = new Consumer(queue); 

producer.MakeStuff(); 
consumer.WriteStuffToFile(); 
+0

जोड़ने के लिए भूल गए, ऐसा करने का कारण यह है कि मैं निर्माता और उपभोक्ता को अलग थ्रेड में रख सकता हूं, और मुख्य धागे को अन्य चीजों को करने के लिए छोड़ सकता हूं। – Mathieson

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