2012-04-11 12 views
7

मैं एकल निर्माता, एकल उपभोक्ता फीफो क्वेरी की जरूरत है क्योंकिक्या ब्लॉकिंग कोलेक्शन <T> का उपयोग एकल-निर्माता, एकल उपभोक्ता फीफो क्वेरी के रूप में करना अच्छा है?

  • मैं उनकी प्राप्ति के क्रम में संदेश संसाधित करने की जरूरत है।
  • मुझे यह एसिंक्रोनस करने की ज़रूरत है क्योंकि कॉलर को संदेश संसाधित करते समय प्रतीक्षा नहीं करनी चाहिए।
  • अगला संदेश प्रसंस्करण केवल तब शुरू किया जाना चाहिए जब पिछला संदेश प्रसंस्करण समाप्त हो जाए। कभी-कभी "प्राप्त करने" संदेशों की आवृत्ति "प्रसंस्करण" संदेशों की आवृत्ति से अधिक है। लेकिन औसतन मैं सभी संदेशों को संसाधित करने में सक्षम होना चाहिए, कभी-कभी मुझे उनमें से "कतार" पैक करना पड़ता है।

तो यह बहुत टीसीपी/आईपी मुझे लगता है, जहाँ आप एक निर्माता और एक उपभोक्ता है की तरह है, कभी-कभी आप, तेजी से आप संसाधित कर सकते हैं संदेश प्राप्त कर सकते हैं ताकि आप उन्हें क्वेरी करने के लिए किया है। जहां आदेश महत्वपूर्ण है और जहां कॉलर बिल्कुल उस चीज़ के साथ क्या कर रहा है उसमें रुचि नहीं लेता है।

यह बहुत आसान लगता है और मुझे लगता है संभावना है कि के लिए सामान्य Queue उपयोग कर सकते हैं, लेकिन मुझे लगता है कि के लिए BlockingCollection उपयोग करने के लिए क्योंकि मैं अपने काम के लिए ManualResetEvent आदि

कैसे उपयुक्त BlockingCollection के साथ किसी भी कोड लिखने के लिए नहीं करना चाहती चाहते हैं और शायद आप कुछ और सुझाव दे सकते हैं?

उत्तर

11

BlockingCollection कक्षा लागू IProducerConsumerCollection इंटरफ़ेस आपकी आवश्यकताओं को पूरी तरह से फिट करता है।

आप दो कार्य बना सकते हैं, एक async निर्माता के लिए और दूसरा उपभोक्ता कार्यकर्ता के रूप में। पूर्व BlockingCollection पर आइटम जोड़ देंगे और बाद में केवल एफआईएफओ ऑर्डर में नए उपलब्ध होने पर उपभोग करेंगे।

निर्माता-उपभोक्त नमूना आवेदन TPL Tasks और BlockingCollection का उपयोग कर:

class ProducerConsumer 
{ 
    private static BlockingCollection<string> queue = new BlockingCollection<string>(); 

    static void Main(string[] args) 
    { 
     Start(); 
    } 

    public static void Start() 
    { 
     var producerWorker = Task.Factory.StartNew(() => RunProducer()); 
     var consumerWorker = Task.Factory.StartNew(() => RunConsumer()); 

     Task.WaitAll(producerWorker, consumerWorker); 
    } 

    private static void RunProducer() 
    { 
     int itemsCount = 100; 

     while (itemsCount-- > 0) 
     { 
      queue.Add(itemsCount + " - " + Guid.NewGuid().ToString()); 
      Thread.Sleep(250); 
     } 
    } 

    private static void RunConsumer() 
    { 
     foreach (var item in queue.GetConsumingEnumerable()) 
     { 
      Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.ffff") + " | " + item); 
     } 
    } 
} 

IProducerConsumerCollection:

को परिभाषित करता है तरीकों निर्माता/उपभोक्ता उपयोग के लिए अभिप्रेत धागे की सुरक्षित संग्रह में हेरफेर करने के। यह इंटरफ़ेस उत्पादक/उपभोक्ता संग्रह के लिए एक एकीकृत प्रतिनिधित्व प्रदान करता है ताकि उच्च स्तर सिस्टम जैसे समेकन। कोलेकुरेंट.ब्लॉकिंग कोलेक्शन (टी का) संग्रह को अंतर्निहित स्टोरेज तंत्र के रूप में उपयोग कर सकता है।

+0

द्वारा किए गए परिवर्तनों के परिणामस्वरूप अपवादों को पकड़ सकते हैं। मुझे आशा है कि अगले कुछ रिलीज में' ब्लॉकिंग कोलेक्शन 'का डिफ़ॉल्ट फीफो कार्यान्वयन नहीं बदला जाएगा , लेकिन यह एक और सवाल है ... – javapowered

+0

मेरा मानना ​​है कि जब तक आप 'आईपॉडसर कॉन्स्यूमर कोलेक्शन' इंटरफ़ेस का संदर्भ दे रहे हैं, तब तक आपको ठीक होना चाहिए, और बीसीएल कक्षाओं के कार्यान्वयन कुछ अन्य तरीकों से फीफो ऑर्डर जैसे परिवर्तन नहीं कर सकते हैं – sll

+2

मुझे लगता है कि स्टार्ट() विधि दो के लिए प्रतीक्षा करती है कार्य पूरा करने के लिए। जाहिर है कि 'निर्माता वर्कर' कार्य समाप्त हो जाएगा, लेकिन 'उपभोक्ता कार्यकर्ता' कभी खत्म नहीं होगा। क्या इसे ध्यान में रखा जाना चाहिए? –

0

चूंकि यह एक कतार है जिसकी आपको आवश्यकता है, क्यों कतार में चिपकना नहीं है? आप Syncrhonized Queue का उपयोग कर सकते हैं।

+0

ब्लॉक नहीं करता है। –

+0

मार्टिन दाएं, [एमएसडीएन] (http://msdn.microsoft.com/en-us/library/system.collections.queue.synchronized.aspx): 'संग्रह के माध्यम से गणना करना आंतरिक रूप से थ्रेड-सुरक्षित प्रक्रिया नहीं है। यहां तक ​​कि जब संग्रह सिंक्रनाइज़ किया जाता है, तब भी अन्य थ्रेड संग्रह को संशोधित कर सकते हैं, जिससे गणनाकर्ता अपवाद फेंकने का कारण बनता है। गणना के दौरान थ्रेड सुरक्षा की गारंटी के लिए, आप या तो संपूर्ण गणना के दौरान संग्रह को लॉक कर सकते हैं या अन्य थ्रेड ' – sll

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