2016-07-28 16 views
7

मुझे बस कुछ चीजों के साथ इस सवाल प्रस्तावना करते हैं:मिश्रण async/परिणाम के साथ इंतजार है

  1. मैं कई अतः कह रही है कि आप ऐसा नहीं करना चाहिए सवाल पढ़ा है यह (जैसे How to safely mix sync and async code के रूप में)
  2. मैं Async/Await - Best Practices in Asynchronous Programming पढ़ा है फिर से कह रही है कि आप ऐसा नहीं करना चाहिए इस

तो मुझे पता है कि यह एक सबसे अच्छा अभ्यास नहीं है, और किसी को भी मुझे इस तरह कह जरूरत नहीं है। यह एक "यह काम क्यों करता है" सवाल है।

मैं 2 बटन और एक स्थिति लेबल है कि एक छोटी सी जीयूआई आवेदन में लिखा है:

कि रास्ते से बाहर के साथ

, यहाँ मेरे सवाल है। बटनों में से एक सिंक और एसिंक 100% समय के साथ डेडलॉक समस्या को पुन: पेश करेगा। दूसरा बटन एक ही एसिंक विधि को कॉल करता है लेकिन यह एक कार्य में लपेटा जाता है, यह एक काम करता है। मुझे पता है कि यह एक अच्छा कोडिंग अभ्यास नहीं है, लेकिन मैं को समझना चाहता हूं क्यों इसमें एक ही डेडलॉक समस्या नहीं है। यहाँ कोड है:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private async Task<string> DelayAsync() 
    { 
     await Task.Delay(1000); 
     return "Done"; 
    } 

    private void buttonDeadlock_Click(object sender, EventArgs e) 
    { 
     labelStatus.Text = "Status: Running"; 

     // causes a deadlock because of mixing sync and async code 
     var result = DelayAsync().Result; 
     // never gets here 
     labelStatus.Text = "Status: " + result; 
    } 

    private void buttonWorking_Click(object sender, EventArgs e) 
    { 
     labelStatus.Text = "Status: Running"; 
     string result = null; 

     // still technically mixes sync and async, but works, why? 
     result = Task.Run(async() => 
     { 
      return await DelayAsync(); 
     }).Result; 

     labelStatus.Text = "Status: " + result; 
    } 
} 

उत्तर

11

यह काम करता है buttonWorking_Click async कोड (DelayAsync के साथ-साथ async लैम्ब्डा Task.Run के लिए पारित किया है), क्योंकि एक मौजूदा SynchronizationContext नहीं है, जबकि buttonDeadlock_Click async कोड (DelayAsync) करता है। आप डीबगर में चलकर और SynchronizationContext.Current देखकर अंतर देख सकते हैं।

मैं अपने ब्लॉग पोस्ट Don't Block on Async Code में डेडलॉक परिदृश्य के पीछे विवरण समझाता हूं।

+0

वास्तव में मैं क्या चाहता था, आप तेजी से जवाब के लिए धन्यवाद देता हूं। – Middas

9

परिदृश्य एक: आप अपनी मेज पर बैठे हैं। एक इनबॉक्स है यह खाली है। कागज़ का एक टुकड़ा अचानक आपके इनबॉक्स में एक कार्य का वर्णन करता है। आप अपने पैरों पर कूदते हैं और कार्य करने के आसपास दौड़ना शुरू करते हैं। लेकिन काम क्या है? यह निम्नलिखित करने के लिए कहता है:

  • "चलने" के लिए व्हाइटबोर्ड बदलें - ठीक है, आप ऐसा करते हैं।
  • एक घंटे बाद अपनी अलार्म घड़ी सेट करें। ठीक है, आप ऐसा करते हैं।
  • कागज का एक नया टुकड़ा बनाएं जो कहता है "जब अलार्म बंद हो जाता है, तो व्हाइटबोर्ड पर शब्द लिखें"। इसे अपने इनबॉक्स में रखो। तुम वो करते हो।
  • व्हाइटबोर्ड पर शब्द लिखा जाने तक कुछ और नहीं करें।
  • अपनी मेज पर वापस जाएं और अगले कार्य को इनबॉक्स में आने की प्रतीक्षा करें।

यह वर्कफ़्लो आपको काम करने से रोकता है क्योंकि पिछले दो चरण गलत क्रम में हैं।

परिदृश्य दो: आप अपनी मेज पर बैठे हैं। एक इनबॉक्स है यह खाली है। कागज़ का एक टुकड़ा अचानक आपके इनबॉक्स में एक कार्य का वर्णन करता है। आप अपने पैरों पर कूदते हैं और कार्य करने के आसपास दौड़ना शुरू करते हैं। लेकिन काम क्या है? यह निम्नलिखित करने के लिए कहता है:

  • "चलने" के लिए व्हाइटबोर्ड बदलें - ठीक है, आप ऐसा करते हैं।
  • अगले क्यूबिकल में डेबी को पेपर का यह दूसरा टुकड़ा दें। ठीक है, आप ऐसा करते हैं।
  • कुछ भी नहीं करें जब तक कि कोई आपको बताए कि उप-कार्य पूरा हो गया है।
  • जब ऐसा होता है, तो अपने व्हाइटबोर्ड पर शब्द को लिखें।
  • अपनी मेज पर वापस जाएं।

आपके द्वारा दिए गए पेपर का टुकड़ा डेबी कहता है? यह कहता है:

  • एक घंटे बाद अपनी अलार्म घड़ी सेट करें। ठीक है, वह वह करती है।
  • जब अलार्म बंद हो जाता है, तो अपने इनबॉक्स में पेपर का एक टुकड़ा डालकर कहें कि मिडस को बताएं कि आप कर चुके हैं।

इस कार्यप्रवाह अभी भी में भयानक है कि (1) तुम वहाँ बैठे हैं कुछ नहीं कर रहे हैं, जबकि आप डेबी अलार्म घड़ी के लिए प्रतीक्षा बंद होने के लिए, और (2) यदि आप दो श्रमिकों की समय बर्बाद कर रहे हैं जब आप कर सकते थे एक ही कार्यकर्ता सभी काम करता है। श्रमिक महंगे हैं।

लेकिन यह वर्कफ़्लो आपको अंततः काम करने से नहीं रोकता है। यह डेडलॉक नहीं करता है क्योंकि आप पर काम नहीं कर रहे हैं जो आप भविष्य में में करने जा रहे हैं, आप काम करने के लिए किसी और को का इंतजार कर रहे हैं।

(मैं ध्यान दें कि यह क्या अपने कार्यक्रम में हो रहा है के लिए एक सटीक सादृश्य नहीं है, लेकिन यह काफी निकट भर में विचार प्राप्त करने के लिए है।)

+0

मैं आपके उदाहरणों की सराहना करता हूं, यह इसे और अधिक समझने योग्य संदर्भ में रखने में मदद करता है कि इस परिदृश्य के साथ डेडलॉक्स क्यों होते हैं। – Middas

+3

यही कारण है कि मैं एरिक के स्टैक ओवरफ्लो आरएसएस फ़ीड की सदस्यता लेता हूं। यहां तक ​​कि यदि आप उत्तर जानते हैं, तो भी आप सहकर्मियों को चीजों को समझाने के लिए अतिरिक्त अंतर्दृष्टि और/या महान तरीके प्राप्त कर सकते हैं। –

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