5

का उपयोग किए बिना सभी कार्यों (बनाए गए कार्य और उप-कार्य) पर कैसे प्रतीक्षा करें मुझे एक समवर्ती सॉफ़्टवेयर बनाना होगा जो कई कार्य बनाएगा, और प्रत्येक कार्य एक और कार्य उत्पन्न कर सकता है (जो एक और कार्य भी उत्पन्न कर सकता है .. ।)।TaskCreationOptions.AttachedToParent

मुझे यह आवश्यक है कि कार्य शुरू करने वाली विधि को कॉल अवरुद्ध कर रहा है: कोई कार्य नहीं सभी कार्य और सबटास्क पूरा होने से पहले।

मैं जानता हूँ कि इस TaskCreationOptions.AttachedToParent संपत्ति वहाँ है, लेकिन मुझे लगता है कि फिट नहीं होगा:

सर्वर कम से कम 8 कोर की तरह कुछ होगा, और प्रत्येक कार्य के 2-3 उपकार्य बन जाएगा, ताकि अगर मैं सेट AttachedToParent विकल्प, मुझे लगता है कि दूसरा उप-कार्य पहले उप-कार्य समाप्त होने के तीन कार्यों से पहले शुरू नहीं होगा। तो मेरे पास एक सीमित मल्टीटास्किंग होगा।

इस प्रक्रिया के पेड़ के साथ

तो:

enter image description here

मैं धारणा है कि अगर मैं AttachedToParent संपत्ति हर सेट मैं एक धागा लांच, बी ई, एफ, जी से पहले समाप्त हो जाती है पूरा कर लें नहीं होगा, इसलिए सी बी खत्म होने से पहले शुरू होगा, और मेरे पास 8 के बजाय केवल 3 सक्रिय थ्रेड होंगे।

यदि मैं संलग्न ToParent संपत्ति नहीं डालता, तो ए बहुत जल्दी समाप्त हो जाएगा और वापस आ जाएगा।

तो मैं यह सुनिश्चित करने के लिए कैसे कर सकता हूं कि अगर मैं इस विकल्प को सेट नहीं करता तो हमेशा मेरे 8 कोर पूरी तरह से उपयोग किए जाते हैं?

+3

छापों पर विश्वास न करें। या तो इसे दस्तावेज़ीकरण में देखें या इसे अपने आप आज़माएं। – svick

उत्तर

2

TaskCreationOptions.AttachedToParent अन्य उप-कार्य शुरू करने से नहीं रोकता है, बल्कि माता-पिता कार्य को बंद होने से रोकता है। तो जब ई, एफ और जी अटैचड टॉपेन्टेंट के साथ शुरू होते हैं, बी को समाप्त होने तक ध्वजांकित नहीं किया जाता है जब तक कि सभी तीन समाप्त नहीं हो जाते हैं। तो यह वैसे ही करना चाहिए जैसा आप चाहते हैं।

source (स्वीकृत उत्तर में)।

2

जैसा कि मैंने नाम दिया है, AttachedToParent आपके इंप्रेशन के अनुसार व्यवहार नहीं करता है। मुझे लगता है कि यह इस मामले में एक अच्छा विकल्प है।

लेकिन यदि आप किसी भी कारण से इसका उपयोग नहीं करना चाहते हैं, तो आप Task.WaitAll() के साथ सभी बच्चे कार्यों को समाप्त करने की प्रतीक्षा कर सकते हैं। हालांकि इसका मतलब है कि आपको उन सभी को संग्रह में रखना होगा।

Task.WaitAll() वर्तमान धागे को अवरुद्ध करता है जब तक कि सभी Task एस समाप्त नहीं हो जाते हैं। यदि आप यह नहीं चाहते हैं और आप .NET 4.5 पर हैं, तो आप Task.WhenAll() का उपयोग कर सकते हैं, जो एक Task वापस करेगा जो सभी Task के समाप्त होने पर समाप्त हो जाएगा।

1

आप TaskFactory इस उदाहरण में जैसे विकल्प बना सकते हैं:

Task parent = new Task(() => { 
var cts = new CancellationTokenSource(); 
var tf = new TaskFactory<Int32>(cts.Token, 
             TaskCreationOptions.AttachedToParent, 
             TaskContinuationOptions.ExecuteSynchronously, 
TaskScheduler.Default); 

// This tasks creates and starts 3 child tasks 
var childTasks = new[] { 
     tf.StartNew(() => Sum(cts.Token, 10000)), 
     tf.StartNew(() => Sum(cts.Token, 20000)), 
     tf.StartNew(() => Sum(cts.Token, Int32.MaxValue)) // Too big, throws Overflow 
}; 

// If any of the child tasks throw, cancel the rest of them 
for (Int32 task = 0; task <childTasks.Length; task++) 
    childTasks[task].ContinueWith( 
    t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted); 

// When all children are done, get the maximum value returned from the 
// non-faulting/canceled tasks. Then pass the maximum value to another 
// task which displays the maximum result 
tf.ContinueWhenAll( 
    childTasks, 
    completedTasks => completedTasks.Where( 
    t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result), CancellationToken.None) 
    .ContinueWith(t =>Console.WriteLine("The maximum is: " + t.Result), 
     TaskContinuationOptions.ExecuteSynchronously); 
}); 

// When the children are done, show any unhandled exceptions too 
parent.ContinueWith(p => { 
    // I put all this text in a StringBuilder and call Console.WriteLine just once 
    // because this task could execute concurrently with the task above & I don't 
    // want the tasks' output interspersed 
    StringBuildersb = new StringBuilder( 
         "The following exception(s) occurred:" + Environment.NewLine); 

    foreach (var e in p.Exception.Flatten().InnerExceptions) 
     sb.AppendLine(" "+ e.GetType().ToString()); 

    Console.WriteLine(sb.ToString()); 
    }, TaskContinuationOptions.OnlyOnFaulted); 

    // Start the parent Task so it can start its children 
    parent.Start();