2009-10-14 13 views
10

मेरे पास एक ऑब्जेक्ट है जिसके लिए बहुत प्रारंभिक आवश्यकता है (एक गोमांस मशीन पर 1-2 सेकंड)। यद्यपि इसे प्रारंभ करने के बाद भी एक सामान्य "नौकरी"एक अंतहीन कार्यकर्ता धागा रखने का सही तरीका?

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

यहाँ है कि मैं क्या है अब तक, किसी भी आलोचना

private void DoWork() 
    { 
     while (true) 
     { 
      if (JobQue.Count > 0) 
      { 
       // do work on JobQue.Dequeue() 
      } 
      else 
      { 
       System.Threading.Thread.Sleep(50); 
      } 
     } 
    } 

का स्वागत किया है सोचा के बाद: मैं सोच रहा था कि मैं इस धागे शान दे इसे हमेशा के लिए चलाने की इनसीड को मारने के लिए आवश्यकता हो सकती है, इसलिए मैं मैं एक जोड़ देगा लगता है नौकरी का प्रकार जो धागे को समाप्त करने के लिए कहता है। इस तरह के धागे को खत्म करने के बारे में कोई भी विचार भी सराहना करता है।

उत्तर

19

आप जरूरतlock वैसे भी करने के लिए है, तो आप कर सकते हैं और WaitPulse:

lock(queue) { 
    queue.Enqueue(item); 
    // if the queue was empty, the worker may be waiting - wake it up 
    if(queue.Count == 1) { Monitor.PulseAll(queue); } 
} 

तुम भी this question है, जो आकार को सीमित करता को देखने के लिए चाहते हो सकता है:

while(true) { 
    SomeType item; 
    lock(queue) { 
     while(queue.Count == 0) { 
      Monitor.Wait(queue); // releases lock, waits for a Pulse, 
           // and re-acquires the lock 
     } 
     item = queue.Dequeue(); // we have the lock, and there's data 
    } 
    // process item **outside** of the lock 
} 
की तरह जोड़ने के साथ

कतार का (अवरुद्ध अगर यह बहुत भरा है)।

+0

क्लासिक कतार, लॉक और पल्सिंग। –

+0

+1 बहुत अच्छा ... –

+0

क्यों कुछ लिखा है जो पहले से ही लिखा गया है? पीएफएक्स, बेबी। – Will

2

आपको एक सिंक्रनाइज़ेशन आदिम की आवश्यकता है, जैसे WaitHandle (स्थिर विधियों को देखें)। इस तरह आप कार्यकर्ता धागे को 'सिग्नल' कर सकते हैं कि काम है। यह कतार की जांच करता है और कतार खाली होने तक काम करता रहता है, जिस समय यह म्यूटेक्स को फिर से सिग्नल करने की प्रतीक्षा करता है।

काम वस्तुओं में से एक बनाने के एक से बाहर निकलें आदेश भी हो, ताकि आप कार्यकर्ता धागा जब यह धागा

1

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

यदि .NET ऐसा वर्ग प्रदान करता है, तो मैं इसका उपयोग करने में देखता हूं। एक धागा अवरुद्ध नींद कॉल पर थ्रेड कताई से काफी बेहतर है।

जो काम आप पास कर सकते हैं वह "शून्य" के रूप में सरल हो सकता है; अगर कोड एक शून्य प्राप्त करता है, तो यह जानता है कि समय बीतने और घर जाने का समय है।

1

Parallel Framework पकड़ो। इसमें BlockingCollection<T> है जिसे आप नौकरी कतार के रूप में उपयोग कर सकते हैं। आप इसका उपयोग कैसे करेंगे:

  1. ब्लॉकिंग कोलेक्शन < टी> बनाएं जो आपके कार्यों/नौकरियों को बनाए रखेगा।
  2. जो एक कभी न खत्म होने पाश है कुछ धागे बनाएँ (जबकि (सही) {// कतार बंद नौकरी मिल)
  3. धागे जा रहा
  4. संग्रह जब वे उपलब्ध आने के लिए कार्य जोड़ें सेट

संग्रह में कोई आइटम प्रकट होने तक धागे अवरुद्ध किए जाएंगे। जो भी इसे चालू करता है वह इसे प्राप्त करेगा (सीपीयू पर निर्भर करता है)। मैं अब इसका उपयोग कर रहा हूं और यह बहुत अच्छा काम करता है।

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

+0

क्या आपका मतलब है कि सीटीपी चिह्नित है "यह सीटीपी केवल परीक्षण उद्देश्यों के लिए है।" यकीन नहीं है कि एक महान सिफारिश है ... 4.0 में, ठीक है - लेकिन वह बीटा है! –

1

यदि आपको वास्तव में थ्रेड निकास की आवश्यकता नहीं है (और बस इसे अपने एप्लिकेशन को चालू रखने से रोकना है) तो आप Thread.IsBackground को सत्य पर सेट कर सकते हैं और यह समाप्त हो जाएगा जब सभी गैर पृष्ठभूमि धागे समाप्त हो जाएंगे। विल और मार्क दोनों में कतार संभालने के लिए अच्छे समाधान हैं।

1

मैंने किसी भी प्रकार के while लूप, या स्पंदन या प्रतीक्षा, या वास्तव में Thread ऑब्जेक्ट्स को छूने के बिना पृष्ठभूमि-कार्य कतार लागू की है। और ऐसा लगता है कि काम करता है। (जिसका मेरा मतलब है कि यह पिछले 18 महीनों के लिए किसी भी अप्रत्याशित व्यवहार के बिना हजारों कार्यों को संभालने के उत्पादन वातावरण में रहा है।) यह दो महत्वपूर्ण गुणों वाला एक वर्ग है, Queue<Task> और BackgroundWorker। यहां तीन महत्वपूर्ण विधियां हैं, संक्षेप में:

private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    if (TaskQueue.Count > 0) 
    { 
     TaskQueue[0].Execute(); 
    } 
} 

private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    Task t = TaskQueue[0]; 

    lock (TaskQueue) 
    { 
     TaskQueue.Remove(t); 
    } 
    if (TaskQueue.Count > 0 && !BackgroundWorker.IsBusy) 
    { 
     BackgroundWorker.RunWorkerAsync(); 
    } 
} 

public void Enqueue(Task t) 
{ 
    lock (TaskQueue) 
    { 
     TaskQueue.Add(t); 
    } 
    if (!BackgroundWorker.IsBusy) 
    { 
     BackgroundWorker.RunWorkerAsync(); 
    } 
} 

ऐसा नहीं है कि कोई प्रतीक्षा और स्पंदन नहीं है। लेकिन यह सब BackgroundWorker के अंदर होता है। जब भी कतार में कोई कार्य गिरा दिया जाता है, तब यह उठता है, कतार खाली होने तक चलता है, और फिर सो जाता है।

मैं थ्रेडिंग पर एक विशेषज्ञ से बहुत दूर हूं। का उपयोग करते समय इस तरह की समस्या के लिए System.Threading के साथ गड़बड़ करने का कोई कारण है?

+0

सामान्य रूप से, मैं मानता हूं कि पृष्ठभूमि कार्यकर्ता वर्ग पृष्ठभूमि कार्य के प्रबंधन के लिए अक्सर एक आसान विकल्प होता है। इस मामले में, मुझे आपके कुछ दावों को चुनौती देना है।आप थ्रेडिंग ऑब्जेक्ट्स का उपयोग कर रहे हैं: 'लॉक' कीवर्ड' सिस्टम के लिए सिंटैक्टिक चीनी है। थ्रेडिंग। मॉनिटर.इंटर() 'और' सिस्टम। थ्रेडिंग। मॉनिटर.एक्सिट() '। थोड़ी देर के लूप के बजाय, आपका रनवर्कर पूर्ण ईवेंट हैंडलर 'BackgroundWorker.RunWorkerAsync() 'को कॉल करता है। मुझे लगता है कि इस मामले में लूप का पालन करना आसान हो सकता है जबकि प्रतीक्षा/पल्स का तर्क आसान हो सकता है। –

+0

पर्याप्त मेला। यह शायद मेरे लिए आसान लग रहा है क्योंकि मुझे प्रतीक्षा/नाड़ी के साथ अनुभव नहीं हुआ है। –

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