2016-12-03 10 views
5

चलो कहते हैं कि मैं दो स्वतंत्र async कार्य होते हैं (है कि मैं पर नियंत्रण नहीं है) कि टास्क वस्तुओं बनाएँ:स्वतंत्र सी # कार्यों को कैसे श्रृंखलाबद्ध करें?

Task A(); 
Task B(); 

और कुछ अन्य गैर async समारोह

void X(); 

मैं कैसे एक भी निर्माण करते हैं कार्य श्रृंखला जो इन सभी को अनुक्रम में निष्पादित करती है और संलग्न होने के लिए आगे की निरंतरता (जो एक्स के बाद निष्पादित) की अनुमति देती है?

मैं ऐसा करते हैं तो:

Task Sequential() 
{ 
    return A() 
    .ContinueWith(t => { B(); }) 
    .ContinueWith(t => { X(); }); 
} 

वह काम नहीं करता, क्योंकि बी एक नया टास्क श्रृंखला शुरू कर देंगे। यदि बी को पूरा करने में लंबा समय लगता है, तो एक्स पहले निष्पादित किया जाएगा (साथ ही अनुक्रमिक के कॉलर जारी किए जा सकने वाले कार्य के साथ जारी रख सकते हैं)। मुझे बी कार्य को इसके उदाहरण के रूप में, एक कार्य श्रृंखला में अंतिम तत्व होने की आवश्यकता है।

मैं ऐसा करते हैं तो:।

Task Sequential() 
{ 
    return A() 
    .ContinueWith(t => { B().ContinueWith(t => { X(); }); }); 
} 

कि केवल आंशिक रूप से समस्या का हल है, क्योंकि भले ही ए, बी और एक्स अब अनुक्रमिक क्रम में निष्पादित करेंगे, अगर फोन करने वाले अनुक्रमिक() ContinueWith करता है, कि निरंतरता एक्स और 0 के बाद समानांतर में निष्पादित होगा,

+0

एलेक्स के जवाब जिस तरह से आप जाना चाहता हूँ है। लेकिन आपके उद्देश्यों के लिए, जो आप पूरा करने की कोशिश कर रहे हैं उसे एक वादे के उपयोग की आवश्यकता होगी (जो 'कार्य पूर्णीकरण स्रोत ' सेवा करता है)। –

+1

'टास्क। वैटएल (ए(), बी()) नहीं है। जारी रखें (टी => एक्स()) 'एक विकल्प, यदि आप कहते हैं कि' ए' और 'बी' स्वतंत्र हैं? – VMAtm

+0

@VMAtm, आपका मतलब है 'कार्य। जब सभी'। –

उत्तर

7

क्या प्रतीक्षा करने का कोई कारण नहीं है? उदाहरण के लिए,

async Task Sequential() 
{ 
    await A(); 
    await B(); 
    X(); 
} 
+0

धन्यवाद, यह काम किया! –

4

यह मानते हुए कि आप async/await उपयोग नहीं कर सकते हैं (यदि आप, आप चाहिए कर सकते हैं) अन्य उत्तर में के रूप में सुझाव दिया, वहाँ एक गंधा छोटे से विस्तार विधि .NET में Task की शुरूआत के बाद इस परिदृश्य के लिए पूरा करने के लिए उपलब्ध 4.0: System.Threading.Tasks.TaskExtensions.Unwrap। यह Task<Task> (या Task<Task<TResult>>) लेता है और इसे "0x(या Task<TResult> क्रमशः) में" flattens "करता है, जो बाहरी कार्य, और आंतरिक कार्य दोनों को पूरा करने का प्रतिनिधित्व करता है।

कि विस्तार विधि तरीके के रूप में लिखा जा सकता है का उपयोग करना:

Task Sequential() 
{ 
    return A() 
     .ContinueWith(t => B()).Unwrap() 
     .ContinueWith(t => X()); // You said X() is "non-async", so no Unwrap here. 
} 

परिणामी Task उम्मीद क्रम में, कार्य की पूरी अनुक्रमिक श्रृंखला के पूरा होने का प्रतिनिधित्व करेंगी।

वहाँ भी the concept of "child tasks" मूल रूप से कार्य समानांतर लाइब्रेरी के शुरुआती दिनों में यह बहुत ही उद्देश्य के लिए तैयार है, लेकिन इसका इस्तेमाल करने horrendously मुश्किल है और आवश्यकता है तुम पर कैसे कार्य शुरू कर रहे हैं है, जो आप कर सकते हैं महान नियंत्रण है नहि हे। फिर भी, यह जानने के लायक है (अगर केवल शिक्षा के लिए)।

2

माइक्रोसॉफ्ट के प्रतिक्रियाशील फ्रेमवर्क (NuGet "System.Reactive") का उपयोग करके ऐसा करने के लिए काफी साफ तरीका है।

public Task A() { return Task.Run(() => { "A".Dump(); Thread.Sleep(1000); "A".Dump(); }); } 
public Task B() { return Task.Run(() => { "B".Dump(); Thread.Sleep(1000); "B".Dump(); }); } 
public void X() { "X".Dump(); Thread.Sleep(1000); "X".Dump(); } 

फिर Sequential().Wait(); चल रहा यह पैदा करता है:

public Task Sequential() 
{ 
    return 
    (
     from a in Observable.FromAsync(() => A()) 
     from b in Observable.FromAsync(() => B()) 
     from c in Observable.Start(() => X()) 
     select c 
    ).ToTask(); 
} 

अगर हम पद्धतियां निर्धारित इस हैं

 
A 
A 
B 
B 
X 
X 
संबंधित मुद्दे