2011-12-11 22 views
5

समानांतर रोकने के लिए सबसे प्रभावी तरीका क्या होगा (इसे समाप्त होने से पहले)।समांतर। Foreach C# रोकें और रोकें फंक्शन?

Parallel.ForEach(list, (item) => 
{ 
    doStuff(item); 
}); 
+5

रोकें वापस आ जाएगी? आप इसे क्यों रोकना चाहते हैं? –

+0

रोकें एक अतिरिक्त सुविधा है जिसे मैं जोड़ना चाहता हूं यदि यह संभव है। मैं एक प्रोग्राम है जो दोनों सीपीयू और इंटरनेट कनेक्शन पर भारी है और तेजी से यह भर सकते हैं तो एक ठहराव है कि बुरा नहीं हो सकता है लिख रहा हूँ। मैं सिर्फ वाला रोक कार्यक्षमता को लागू करने और एक और सूची में अधूरा तत्वों की सूची को बचाने के लिए और फिर अगले रन पर उस सूची को फिर से लिखने रहा हूँ। और कहां से रुक गया है जारी रखें। विंडा की तरह किंडा। धन्यवाद। – bbrez1

+0

तो जवाब में से एक तुम एक समाधान दिया [आपको लगता है कि जवाब के रूप में स्वीकार कर लिया निशान चाहिए] (http://stackoverflow.com/faq#howtoask)। –

उत्तर

11

Damien_The_Unbeliver की एक अच्छी विधि है, लेकिन यह केवल तभी होता है जब आप कुछ बाहरी प्रक्रिया लूप को रोकना चाहते हैं। यदि आप सामान्य for या foreach लूप में break का उपयोग करने जैसे लूप को तोड़ना चाहते हैं तो आपको a overload का उपयोग करने की आवश्यकता होगी जिसमें लूप बॉडी के पैरामीटर में से एक के रूप में ParallelLoopState है। ParallelLoopState में दो कार्य हैं जो आप करना चाहते हैं, Stop() और Break() के लिए प्रासंगिक हैं।

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

समारोह Break() प्रदर्शन बिल्कुल Stop() के रूप में ही है, लेकिन यह भी है कि आइटम है कि आप पर Break() कहा जाता है से पहले आया IEnumerable के सभी तत्वों का मूल्यांकन करेंगे। यह तब उपयोगी होता है जब आप परवाह नहीं करते कि तत्वों को किस क्रम में संसाधित किया जाता है, लेकिन आपको उस बिंदु तक सभी तत्वों को संसाधित करना होगा जिन्हें आपने रोक दिया था।

ParallelLoopResult का निरीक्षण करें कि फोरच जल्दी से बंद हो गया है या नहीं, और यदि आपने Break() का उपयोग किया है, तो यह सबसे कम संख्या वाली आइटम को संसाधित करता है।

Parallel.ForEach(list, (item, loopState) => 
    { 
     bool endEarly = doStuff(item); 
     if(endEarly) 
     { 
      loopState.Break(); 
     } 
    } 
    ); 
//Equivalent to the following non parallel version, except that if doStuff ends early 
// it may or may not processed some items in the list after the break. 
foreach(var item in list) 
{ 
    bool endEarly = doStuff(item); 
    if(endEarly) 
    { 
     break; 
    } 
} 

यहाँ कोई फर्क नहीं पड़ता कि यह कैसे काम यह हमेशा 2 वापस आ जाएगी एक जवाब के रूप में ऊपर विभाजन एक और अधिक व्यावहारिक उदाहरण

static bool[] list = new int[]{false, false, true, false, true, false}; 

long LowestElementTrue() 
{ 
    ParallelLoopResult result = Parallel.ForEach(list, (element, loopState) => 
    { 
     if(element) 
      loopState.Break(); 
    } 
    if(result.LowestBreakIteration.IsNull) 
     return -1; 
    else 
     return result.LowestBreakIteration.Value; 
} 

है।

मान लें कि प्रोसेसर इसे संसाधित करने के लिए दो धागे भेजता है, पहला थ्रेड तत्व 0-2 और दूसरी थ्रेड प्रक्रिया तत्वों को 3-5 प्रक्रिया करता है।

 
Thread 1:    Thread 2 
0, False, continue next 3, False, continue next 
1, False, continue next 4, True, Break 
2, True, Break   5, Don't process Broke 

अब सबसे कम सूचकांक तोड़ से बुलाया गया था 2 था, इसलिए ParallelLoopResult.LowestBreakIteration 2 हर बार वापस आ जाएगी, कोई चाहे कितना धागे टूट रहे हैं क्योंकि यह हमेशा 2.

यहाँ संख्या तक पर कार्रवाई करेंगे एक उदाहरण कैसे रोकें इस्तेमाल किया जा सकता है।

static bool[] list = new int[]{false, false, true, false, true, false}; 

long FirstElementFoundTrue() 
{ 
    long currentIndex = -1; 
    ParallelLoopResult result = Parallel.ForEach(list, (element, loopState, index) => 
    { 
     if(element) 
     { 
      loopState.Stop(); 

      //index is a 64 bit number, to make it a atomic write 
      // on 32 bit machines you must either: 
      // 1. Target 64 bit only and not allow 32 bit machines. 
      // 2. Cast the number to 32 bit. 
      // 3. Use one of the Interlocked methods. 
      Interlocked.Exchange (ref currentIndex , index); 
     } 
    } 
    return currentIndex; 
} 

निर्भर करता है कि यह कैसे काम विभाजन यह या तो वापस आ जाएगी 2 या 4 जवाब के रूप में।

मान लीजिए कि प्रोसेसर इस पर कार्रवाई करने के दो धागे डिस्पैच करते हैं, पहले धागा तत्वों 0-2 संसाधित करता है और 2 धागा तत्वों 3-5 संसाधित करता है।

 
Thread 1:     Thread 2 
0, False, continue next 3, False, continue next 
1, False, continue next 4, True, Stop 
2, Don't process, Stopped 5, Don't process, Stopped 

इस मामले में यह उत्तर के रूप में 4 लौटाएगा। आइए एक ही प्रक्रिया को देखते हैं, लेकिन यदि यह 0-2 और 3-5 के बजाय हर दूसरे तत्व को संसाधित करता है।

 
Thread 1:     Thread 2 
0, False, continue next  1, False, continue next 
2, True, Stop    3, False, continue next 
4, Don't process, Stopped 5, Don't process, Stopped 

इस समय यह 2 के बजाय 4.

2

एक Parallel.ForEach रोकने में सक्षम हो के लिए, आपको भार के कि एक ParallelOptions पैरामीटर स्वीकार करता है में से एक का उपयोग कर सकते हैं और उन विकल्पों में एक CancellationToken शामिल हैं। अधिक जानकारी के लिए

Cancellation देखें।

को रोककर, मुझे नहीं लगता कि आप सामान्य रूप से ऐसा क्यों करना चाहते हैं। हो सकता है कि आप Barrier (जो एकाधिक थ्रेड के बीच प्रयासों को समन्वयित करने के लिए उपयोग किया जाता है, कहें कि अगर उन्हें भाग भाग को जारी रखने से पहले भाग ए को पूरा करने की आवश्यकता है), लेकिन मुझे नहीं लगता कि आप Parallel.ForEach के साथ इसका उपयोग करेंगे, आप नहीं जानते कि कितने प्रतिभागी होंगे।

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