2016-04-28 8 views
7

मैं सीख रहा हूं कि कंसोल एप्लिकेशन में एसिंक फ़ंक्शन का उपयोग कैसे करें लेकिन कार्य नहीं कर सकता। जब तक सभी कार्य पूरा नहीं हो जाते हैं तब तक सभी प्रतीक्षा करें। निम्नलिखित कोड में क्या गलत है? यह तुल्यकालिक रूप से काम करता है। पहले ही, आपका बहुत धन्यवाद।कार्य। जब सभी प्रतीक्षा नहीं कर रहे हैं

static void Main(string[] args) 
{ 
    ... 
    IncluiValores(...); 
    ... 
} 

static async void IncluiValores(...) 
{ 
    Task<List<int>> res1 = att.GetAIDBAPI(att); 
    Task<List<int>> res2 = att.GetAIDBAPI(att2); 

    List<int>[] res = await Task.WhenAll(res1, res2); 

    ... 
} 

अद्यतन - फंक्शन परिभाषा:

public async Task<List<int>> GetAIDBAPI(Attributes attributes) 
    { 

     List<int> results = null; 

     Connections client0 = new Connections(); 
     HttpClient client = client0.OpenAPIConnection(attributes.User[0], attributes.Pwd, attributes.Server, attributes.Chave, attributes.Server2); 
     HttpResponseMessage response = await client.PostAsJsonAsync("api/Attributes/ID/Bulk", attributes); 

     if (response.IsSuccessStatusCode) 
     { 
      var content = await response.Content.ReadAsStringAsync(); 
      results = JsonConvert.DeserializeObject<dynamic>(content).ToObject<List<int>>(); 
     } 
     else 
     { 
      var content = "[{-1}]"; 
      var result = JsonConvert.DeserializeObject<dynamic>(content); 
      results = result.ToObject<List<int>>(); 
     } 

     return results; 

    } 

अद्यतन 2 - अलग संदर्भ

static void Main(string[] args) 
{ 
    AsyncContext.Run(() => MainAsync(args)); 
} 

static async void MainAsync(string[] args) 
{ 
    await IncluiValores(...); 
} 

static async Task IncluiValores(...) 
{ 
    Task<List<int>> res1 = att.GetAIDBAPI(att); 
    Task<List<int>> res2 = att.GetAIDBAPI(att2); 

    List<int>[] res = await Task.WhenAll(res1, res2); // <- Error here 
    //Collection was modified; enumeration operation may not execute 
    ... 
} 
//Tried to change to code below but it does not wait. 
static async Task IncluiValores(...) 
{ 
    Task<List<int>> res1 = att.GetAIDBAPI(att); 
    Task<List<int>> res2 = att.GetAIDBAPI(att2); 

    await Task.WhenAll(res1, res2); // <- No error, just doesn't wait. 
    list.Add(res1.Result[0]); 
} 
+0

GetAIDBAPI की परिभाषा कैसी दिखती है? – BoltClock

+0

परिभाषा शामिल है। – Gabriel

+0

आपका कॉलिंग कोड कहां स्थित है? यदि यह मुख्य में है, तो यह सही तरीके से काम नहीं करेगा। यदि यह अपनी एसिंक विधि में है, तो उस विधि के लिए कार्य कैसे शुरू किया जा रहा है? – BoltClock

उत्तर

4

आप एक async void विधि है, जो स्वाभाविक मतलब है कि आप await का कोई रास्ता नहीं ing है कॉल कर रहे हैं परिणाम। जब भी आप await छोड़ देते हैं, तो आप सिंक्रनाइज़ेशन श्रृंखला तोड़ रहे हैं। await के माध्यम से "resynchronizing" की बजाय ऑपरेशन वास्तव में असीमित रूप से होता है। नियंत्रण कॉलर को वापस कर दिया जाता है, जबकि (भविष्य में कभी-कभी) ऑपरेशन असीमित रूप से फिर से शुरू होता है।

याद रखें, awaitreturn है। यह केवल await का लगातार उपयोग है जो आपको सिंक्रनाइज़ेशन देता है। async void का उपयोग करना बंद करें - इसे async Task पर बदलें और सुनिश्चित करें कि आप await परिणाम सही तरीके से प्राप्त करें। यह आपके MainAsync विधि के लिए भी जाता है। Task एसिंक विधियों के void है।

केवल एक ही मामला है जहां आपको कभी भी async void देखना चाहिए, और यह विरासत ढांचे के ईवेंट हैंडलर (जैसे विनफॉर्म में) के सिंक्रनाइज़ेशन संदर्भ में है। Task वापस करने के लिए async विधि के लिए यह संभव है, वास्तव में, वास्तव में, वास्तव में यह करना चाहिए। श्रृंखला तोड़ो मत।

2

त्रुटि यह है कि आपका मुख्य कार्य प्रक्रिया IncluiValores को पूरा करने के लिए इंतजार नहीं कर रहा है। प्रक्रिया से पहले आपका मुख्य कार्यक्रम खत्म हो जाता है IncluiValores समाप्त हो गया है।

इस त्रुटि के कारण मुझे लगता है कि आपको अभी भी कुछ परेशानी है समझने में क्या होता है जब आप async-await का उपयोग करते हैं।

स्टैक ओवरफ्लो पर कोई भी व्यक्ति (मुझे अब यह नहीं मिल रहा है), मुझे निम्नलिखित रूपक का उपयोग करके समझाया।

अलावा: मैं के लिए बीच में
It is in this interview with Eric Lippert
खोजें कहीं metaphore पाया async-का इंतजार
समाप्ति ADITION

मान लीजिए आप नाश्ता बनाने की जरूरत है। आप कुछ रोटी टोस्ट करना चाहते हैं, कुछ अंडे उबालें और कुछ चाय बनाना चाहते हैं।

तुल्यकालिक टोस्टर में

  • रखें रोटी और जब तक रोटी टोस्ट है
  • टोस्टर से रोटी निकालें प्रतीक्षा करें।
  • प्रारंभ उबलते पानी, जब तक पानी फोड़े
  • उबलते पानी में कुछ अंडे रखो और 7 मिनट तक प्रतीक्षा अंडे तैयार
  • पानी से अंडे निकालें हैं इंतजार
  • अपने चाय के लिए
  • प्रारंभ उबलते पानी और पानी के उबलने तक प्रतीक्षा करें
  • जब पानी उबालता है तो आप इसे टीपोट में डालते हैं और कुछ चाय के पत्तों को जोड़ते हैं और 4 मिनट
  • अंत में आप सबकुछ एक साथ प्राप्त करते हैं और इसे अपनी नाश्ते की मेज पर ले जाते हैं।

आप देखते हैं कि आप बहुत इंतज़ार कर रहे हैं जो समय बर्बाद है, यह उल्लेख न करें कि आपकी रोटी चाय खत्म होने तक ठंडा हो सकती है।

यह बहुत अधिक कुशल हो सकता है अगर आप हर समय के लिए इंतजार नहीं किया था, लेकिन का उपयोग कर async-का इंतजार एक साथ

बातें शुरू होगा: के रूप में एक धागा का उपयोग कर अतुल्यकालिक

  • प्रारंभ तुल्यकालिक मामला: टोस्टर
  • में रोटी डालें लेकिन अब आप रोटी को टोस्ट तक इंतजार नहीं करते हैं। याद रखें कि रोटी को टोस्ट करने पर आपको क्या करना चाहिए (इसे कार्य ए के रूप में याद रखें)
  • उबलते पानी को शुरू करें, लेकिन पानी को उबालने के लिए प्रतीक्षा न करें। याद रखें कि पानी को उबालने के दौरान आपको क्या करना चाहिए (इसे टास्क बी के रूप में याद रखें)
  • अपनी चाय के लिए उबलते पानी को शुरू करें, लेकिन वेटर को फोड़ा करने की प्रतीक्षा न करें। याद रखें कि चाय केतली फोड़े के दौरान आपको क्या करना चाहिए (इसे टास्क सी के रूप में याद रखें)

  • किसी भी कार्य ए/बी/सी समाप्त होने तक प्रतीक्षा करें। कार्य को समाप्त होने पर आपको क्या करना चाहिए, इसे याद रखें। अगर इसे किसी अन्य प्रतीक्षा की आवश्यकता है (अंडे या चाय तैयार होने के लिए समय), इसके लिए इंतजार न करें, लेकिन इसे कार्य डी और ई के रूप में याद रखें और सभी तैयार कार्यों के लिए प्रतीक्षा करना शुरू करें।

ध्यान दें कि इस विधि में अभी भी केवल एक ही व्यक्ति है जो सभी चीजें कर रहा है। यदि आप इस तरह से async-await का उपयोग करते हैं, तो केवल एक धागा शामिल है। यह धागा केवल प्रतीक्षा कर रहा है अगर वास्तव में ऐसा करने के लिए कुछ भी नहीं है। इसका लाभ यह है कि आपको कई धागे का उपयोग करते समय आम तौर पर सामना करने वाली समस्याओं का सामना नहीं करना पड़ता है।

अतुल्यकालिक कई धागे

आप कई रसोइयों किराया सकता है का उपयोग करते हुए: टोस्ट रोटी के लिए और दूसरा जब तुम tead बनाने के अंडे उबालने के लिए। यह एक महंगी विधि है: कई धागे शुरू करें, जबकि धागे कुछ भी नहीं कर रहे हैं लेकिन अधिकांश समय प्रतीक्षा करें। आपको यह भी सुनिश्चित करने के लिए तीन कुक को सिंक्रनाइज़ करना पड़ता है कि वे एक ही समय में एक-फायर स्टोव का उपयोग नहीं करते हैं।

स्टीफन Cleary एक व्यापक लेख कि Async and Await में इस async-का इंतजार व्यवहार का वर्णन लिखा था कि कैसे चाय बनाने के लिए अब तक (आप स्टीफन धन्यवाद!)

static void Main(string[] args) 
{ 
    var breakFast = await Task.Run(() => MakeBreakFast()); 
    // once here I know breakfast is ready 
    Eat(breakFast); 
} 
private static async Task<BreakFast> MakeBreakFast() 
{ 
    var taskToastBread = ToastBreadAsync(); 
    // do not await. As soon as the procedure awaits come back to do the next statement: 
    var taskBoilEggs = BoilEggsAsync(); 
    // again do not await. Come back as the procedure awaits 
    var taskMakeTea = MakeTeaAsync(); 
    // do not wait, but come bask as soon as the procedure await 

    // now wait until all three tasks are finished: 
    await Task.WhenAll (new Task[] {taskToasBread, taskBoilEggs, taskMakeTea}); 
    // if here: all tasks are finished. Property Result contains the return value of the Task: 
    return new BreakFast() 
    { 
     Toast = taskToastBread.Result, 
     Eggs = taskBoilEggs.Result, 
     Tea = taksMakeTea.Result, 
    } 
} 

private static Task<Toast> ToastBreadAsync() 
{ 
    var sliceOfBread = Loaf.CutSliceOfBread(); 
    Toaster.Insert(sliceOfBread); 
    await Toaster.Toast(); 
    // the function does not wait but return to the caller. 
    // the next is done when the caller await and the toaster is ready toasting 
    var toast = Toaster.Remove(); 
    return Toast(); 
} 

private static Task<Eggs> BoilEggsAsync() 
{ 
    var eggPan = ... 
    await eggPan.BoilWater(); 
    var eggs = Fridge.ExtreactEggs(); 
    EggPan.Insert(eggs); 
    await Task.Delay(TimeSpan.FromMinutes(7)); 
    return EggPan.Remove(); 
} 

आप शायद पता चल जाएगा।

+0

मैंने इस प्रतिलिपि को "नाश्ते बनाने" का जवाब अब तक कई बार पढ़ा है, मुझे लगता है कि मुझे बिल्कुल पता है * सबकुछ * टोस्टिंग रोटी और उबलते अंडे (पाठ्यक्रम के समानांतर में) के बारे में जानना है। –

+0

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

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