2010-09-03 21 views
16

मैं नई सी # 4.0 Parallel.ForEach फंक्शन का उपयोग करके वस्तुओं का एक सूची पर समानांतर कार्यों को निष्पादित करने की कोशिश कर रहा हूँ। यह एक बहुत लंबी रखरखाव प्रक्रिया है। मैं इसे सूची के क्रम में निष्पादित करना चाहता हूं ताकि मैं पिछले बिंदु पर निष्पादन को रोक और जारी रख सकूं। मैं यह कैसे करु?Parallel.ForEach आदेश दिया निष्पादन

यहां एक उदाहरण है। मेरे पास वस्तुओं की एक सूची है: a1 to a100

a1, a51, a2, a52, a3, a53... 

मैं इस क्रम में हैं:: यह वर्तमान आदेश है

a1, a2, a3, a4... 

मैं कुछ वस्तुओं के साथ ठीक क्रम से बाहर चलाया जा रहा हूँ, लेकिन जब तक मैं इस सूची जहां में एक बिंदु मिल सकता है मैं कह सकता हूं कि इस बिंदु से पहले सभी वस्तुओं को चलाया गया था। मैंने समांतर प्रोग्रामिंग csharp whitepaper पढ़ा और इसके बारे में कुछ भी नहीं देखा। ParallelOptions कक्षा में इसके लिए कोई सेटिंग नहीं है।

उत्तर

1

एक वैकल्पिक सुझाव के रूप में, आप रिकॉर्ड कर सकता है जो वस्तु को चलाने की है और फिर जब तुम वस्तुओं जो पहले से ही समाप्त हो गया है बाहर करने के लिए फिर से शुरू exection सूची को फ़िल्टर।

इस आवेदन के पुनरारंभ होने के दौरान जारी रहता होने की जरूरत है, तो आप पहले से ही आईडी निष्पादित वस्तुओं की के स्टोर कर सकते हैं (मैं यहाँ मान वस्तुओं कुछ अद्वितीय पहचानकर्ता है)।

+0

धन्यवाद क्रिस। मैंने PLINQ के साथ परीक्षण किया और यह पर्याप्त है लेकिन मैं बहिष्कृत वस्तुओं की एक सूची भी रखूंगा। –

2

आप Parallel.Break का उपयोग करते हैं तो आप पाश guarenteed कर रहे हैं कि दिए गए मान नीचे सभी सूचकांकों के बाद मार दिया जाएगा समाप्त करने के लिए। यह उतना करीब है जितना आप प्राप्त कर सकते हैं। यहां उदाहरण का उपयोग करता है लेकिन ForEach के समान ओवरलोड हैं।

int n = ... 
var result = new double[n]; 

var loopResult = Parallel.For(0, n, (i, loopState) => 
{ 
    if (/* break condition is true */) 
    { 
     loopState.Break(); 
     return; 
    } 
    result[i] = DoWork(i); 
}); 

if (!loopResult.IsCompleted && 
     loopResult.LowestBreakIteration.HasValue) 
{ 
    Console.WriteLine("Loop encountered a break at {0}", 
         loopResult.LowestBreakIteration.Value); 
} 

एक foreach पाश में, एक यात्रा सूचकांक आंतरिक रूप से प्रत्येक विभाजन में प्रत्येक तत्व के लिए उत्पन्न होता है। निष्पादन आदेश से बाहर होता है लेकिन ब्रेक के बाद आप जानते हैं कि LowestBreakIteration से कम सभी पुनरावृत्तियों को पूरा कर लिया जाएगा।

http://parallelpatterns.codeplex.com/

MSDN पर उपलब्ध "Microsoft .NET के साथ समानांतर प्रोग्रामिंग" से लिया। http://msdn.microsoft.com/en-us/library/ff963552.aspx देखें। इस परिदृश्य को "लूप से बाहर तोड़ने" खंड में शामिल है।

यह भी देखें: http://msdn.microsoft.com/en-us/library/dd460721.aspx

0

जो इस सवाल भर आता है किसी और के लिए - आप एक सरणी या सूची (बजाय एक IEnumberable से) पर पाशन कर रहे हैं, आप Parallel.Foreach का अधिभार कि देता है का उपयोग कर सकते मूल आदेश को बनाए रखने के लिए तत्व सूचकांक भी।

string[] MyArray; // array of stuff to do parallel tasks on 
string[] ProcessedArray = new string[MyArray.Length]; 
Parallel.ForEach(MyArray, (ArrayItem,loopstate,ArrayElementIndex) => 
{ 
    string ProcessedArrayItem = TaskToDo(ArrayItem); 
    ProcessedArray[ArrayElementIndex] = ProcessedArrayItem; 
}); 
1

किसी को भी एक सरल उपाय की तलाश में के लिए, मैं निम्नलिखित प्रश्न का उत्तर के भाग के रूप में 2 विस्तार तरीकों (एक PLINQ का उपयोग कर और एक Parallel.ForEach का प्रयोग करके) पोस्ट किया है:

Ordered PLINQ ForAll

1

Do इस तरह कुछ:

int current = 0; 
object lockCurrent = new object(); 

Parallel.For(0, list.Count, 
      new ParallelOptions { MaxDegreeOfParallelism = MaxThreads }, 
      (ii, loopState) => { 
        // So the way Parallel.For works is that it chunks the task list up with each thread getting a chunk to work on... 
        // e.g. [1-1,000], [1,001- 2,000], [2,001-3,000] etc... 
        // We have prioritized our job queue such that more important tasks come first. So we don't want the task list to be 
        // broken up, we want the task list to be run in roughly the same order we started with. So we ignore tha past in 
        // loop variable and just increment our own counter. 
        int thisCurrent = 0; 
        lock (lockCurrent) { 
         thisCurrent = current; 
         current++; 
        } 
        dothework(list[thisCurrent]); 
       }); 

आप देख सकते हैं कि जब आप लूप के समानांतर से बाहर निकलते हैं तो आपको अंतिम सूची आइटम पता चलेगा निष्पादित किया जाए, मान लीजिए कि आप सभी धागे तोड़ने से पहले खत्म कर दें। मैं PLINQ या LINQ का बड़ा प्रशंसक नहीं हूं। मैं ईमानदारी से नहीं देखता कि LINQ/PLINQ लिखने के लिए कैसे बनाए रखने योग्य स्रोत कोड या पठनीयता .... समानांतर।एक बेहतर समाधान है।

-1

आप अपना कोड भी रख सकते हैं, और एक उत्तर देने से पहले List.Sort() कर सकते हैं।

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