2015-02-18 10 views
7

इस कोड पर एक नज़र डालें:कितना जब तक कार्य Task.ContinueWith भीतरी का इंतजार खत्म

private async Task InnerTask(bool outerTaskResult) 
    { 
     Console.WriteLine("2"); 
     await Task.Factory.StartNew(() => Thread.Sleep(10000)); 
     Console.WriteLine("3"); 
    } 

    private async void Button2_Click(object sender, RoutedEventArgs e) 
    { 
     var task = Task.FromResult(false); 
     Task<Task> aggregatedTask = task.ContinueWith(task1 => InnerTask(task1.Result)); 
     Console.WriteLine("1"); 
     await aggregatedTask; 
     Console.WriteLine("4"); 
    } 

वांछित उत्पादन होता है:

1 
2 
3 
4 

लेकिन मैं मिलता है:

1 
2 
4 
3 

इनरटास्क को एक अलग थ्रेड पर निष्पादित करने के साथ शायद कुछ करना है।

मैं ContinueWith उपयोग कर रहा हूँ क्योंकि मूल कोड में कार्यों को गतिशील बनाया और इस तरह से पंक्तिबद्ध रहे हैं।

का उपयोग करना।() विधि (नीचे देखें) काम करता है, लेकिन मुझे लगता है कि यह एक बुरा विचार है, क्योंकि विधि अवरुद्ध हो रही है।

task.ContinueWith(task1 => InnerTask(task1.Result).Wait()) 

यहां सही दृष्टिकोण क्या है?

उत्तर

8

आप TaskExtensions.Unwrap() (जो Task<Task> पर एक विस्तार विधि है) का उपयोग outter कार्य खोलने में कर सकते हैं और पुनः प्राप्त भीतरी एक:

private async void Button2_Click(object sender, RoutedEventArgs e) 
{ 
    var task = Task.FromResult(false); 
    Task aggregatedTask = task.ContinueWith(task1 => InnerTask(task1.Result)).Unwrap(); 
    Console.WriteLine("1"); 
    await aggregatedTask; 
    Console.WriteLine("4"); 
} 

ध्यान दें कि ContinueWith शैली निरंतरता आप कर सकते हैं के बजाय इस पूरे बात को आसान बनाने, await आपके कार्यों पर:

private async void Button2_Click(object sender, RoutedEventArgs e) 
{ 
    var task = Task.FromResult(false); 

    Console.WriteLine("1"); 

    var result = await task; 
    await InnerTask(result); 

    Console.WriteLine("4"); 
} 
+0

'अनवरप' वास्तव में आवश्यक नहीं है। सवाल में 'प्रतीक्षा एटिलेटेड टास्क 'का वापसी मूल्य वास्तव में आंतरिक कार्य है। –

+0

वह एक 'टास्क ', यह outter कार्य वह पर awating है यही कारण है कि इसे पूरा करने से पहले है है, * * outter 'Console.WriteLine'। वह बस 'इंतजार कर सकता है'। –

+2

@ पानागियोटिस कानावोस ट्रू, यह * आवश्यक * नहीं है, कोई भी दो बार प्रतीक्षा कर सकता है। दोनों एक ही काम करेंगे। यह निश्चित रूप से एक उपयुक्त दृष्टिकोण है। सी # 5.0 में आप वास्तव में 'अनवर्र' को कार्यान्वित कर सकते हैं: 'सार्वजनिक स्थैतिक एसिंक कार्य अनवरत (यह कार्य कार्य) {प्रतीक्षा कार्य का इंतजार; } '(सी # 4.0 संस्करण वास्तव में कष्टप्रद और कठिन है।) – Servy

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