2012-11-26 20 views
5

मैं Task एस श्रृंखला बनाना चाहता हूं, फिर श्रृंखला को समानांतर में शुरू करना चाहता हूं।श्रृंखला कार्य करने के लिए उचित तरीका

 var taskOrig = new Task(() => { }); 
     var task = taskOrig; 
     foreach (var msg in messages) 
     { 
      task=task.ContinueWith(t => Console.WriteLine(msg)); 
     } 
     taskOrig.Start(); 

सब कुछ एक छोटे से पूर्णतावादी को छोड़कर ठीक काम करता है मेरे अंदर खाली विधि पहले () => { } निष्पादित होने पसंद नहीं करता: इस स्निपेट मेरे सवाल का वर्णन करने के लिए है।

क्या इससे बचने का कोई तरीका है?

मुझे समझ में आता है कि यह प्रदर्शन को मुश्किल से प्रभावित करता है (जब तक कि आप इसे वास्तव में अक्सर नहीं करते), लेकिन फिर भी। मेरे मामले में प्रदर्शन मामलों, इसलिए जांच करें कि प्रत्येक पुनरावृत्ति में कार्य मौजूद है या नहीं, यह करने का तरीका नहीं है।

if(messages.Length > 0) 
{ 
    Task task = new Task(t => Console.WriteLine(messages[0])); 

    for(int i = 1; i < messages.Length; i++) 
    { 
     task = task.ContinueWith(t => Console.WriteLine(messages[i])); 
    } 
    task.Start(); 
} 
+1

"मेरे मामले में प्रदर्शन महत्वपूर्ण है अत: पता चल सके कि काम मौजूद है में हर यात्रा नहीं है

एक अन्य विकल्प कुछ इस तरह उपयोग करने के लिए किया जाएगा इसे करने का तरीका। ": जो समय लगता है वह वास्तव में कार्य को निष्पादित करने की तुलना में नगण्य है। जब तक आप वास्तव में एक प्रदर्शन हिट नहीं मापा है, यह स्पष्ट रूप से समयपूर्व अनुकूलन का मामला है। –

+0

@ थॉमस लेवेस्क आप शायद सही हैं, मैंने सोचा कि शायद मुझे 'टास्क' बनाने एपीआई में कुछ याद आया। मुझे बाद में प्रदर्शन हिट मापने का मौका मिलेगा। – Anri

+0

आपको टीपीएल डेटाफ्लो दिलचस्प – sll

उत्तर

3

आप किए जा सकेंगे:

+0

एक नोट: 'टास्क। फ्रॉम रिसेट()' नेट 4.5 में नया है, नेट 4.0 में, आपको इसे 'कार्य पूर्णीकरण स्रोत' का उपयोग करके मैन्युअल रूप से करने की आवश्यकता होगी। – svick

+0

@ एसविक राइट, समाधान जोड़ा गया। – Servy

+0

नाइस, थेंक्स, 'टास्क। फ्रॉम रीसेट (शून्य)' - यह वही है जो मैंने कार्य समानांतर lib में छोड़ा – Anri

2

एक तरीका यह है कि ऐसा करने के लिए, पाश में काम बनाने के लिए करता है, तो यह मान शून्य होगा, लेकिन कोड उपलब्ध कराने मेरे लिए बेहतर लग रहा है: शायद यह

Task task = null; 
foreach (var msg in messages) 
{ 
    if (task == null) 
     task = new Task(() => Console.WriteLine(msg)) 
    else 
     task = task.ContinueWith(t => Console.WriteLine(msg)); 
} 
task.Start(); 
+0

तकनीकी रूप से मिल सकता है - हाँ, लेकिन इसका मतलब है कि मुझे इसे हर लूप की जांच करनी होगी ताकि यह धीमा हो जाए। प्रदर्शन मामलों, मुझे यह प्रश्न – Anri

+0

कोड में जोड़ना चाहिए जो आपको प्रदान करता है वास्तव में अच्छा है, लेकिन चलिए अन्य विकल्पों की प्रतीक्षा करें –

1

ऐसा करें:

Task task = Task.FromResult<object>(null); 
foreach (var msg in messages) 
{ 
    task = task.ContinueWith(t => Console.WriteLine(msg)); 
} 

पिछला समाधान 4.0 में काम नहीं करेगा। 4.0 में आप के बजाय निम्न कार्य पूरे करने होंगे: (। आप SetResult को foreach पाश से पहले स्थानांतरित कर सकते हैं यदि आप चाहें)

var tcs = new TaskCompletionSource<object>(); 
Task task = tcs.Task; 
foreach (var msg in messages) 
{ 
    task = task.ContinueWith(t => Console.WriteLine(msg)); 
} 

tcs.SetResult(null); 

तकनीकी तौर पर यह एक ही नहीं है के रूप में निरंतरता निष्पादित करते समय शुरू कर देंगे आप अभी भी और जोड़ रहे हैं। हालांकि यह एक समस्या होने की संभावना नहीं है।

public static Task ForEachAsync<T>(IEnumerable<T> items, Action<T> action) 
{ 
    return Task.Factory.StartNew(() => 
    { 
     foreach (T item in items) 
     { 
      action(item); 
     } 
    }); 
} 

एक उदाहरण उपयोग होगा::

ForEachAsync(messages, msg => Console.WriteLine(msg)); 
+0

यह सबसे कुशल विकल्प है, लेकिन यह कम पठनीय है ... –

+0

धन्यवाद, यह एक विकल्प है, लेकिन हमेशा काम नहीं करेगा। कभी-कभी आपके पास समकक्ष होता है, और कार्यों को अन्य तरीकों से भी जोड़ा जा सकता है – Anri

+0

@Anri आप भी एक ही चीज़ को गणक के साथ भी कर सकते हैं (मैन्युअल रूप से 'MoveNext()' और 'Current' तक पहुंचकर), सिवाय इसके कि यह और भी होगा कोड और यहां तक ​​कि अधिक गन्दा। – svick

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