मेरे पास एक छोटा प्रोजेक्ट है - WinForms ऑन .net फ्रेमवर्क - बस एक छोटा परीक्षण:

private void button9_Click(object sender, EventArgs e)
{
    string text = GetTitleAsync().Result;
    button9.Text = text;            
}
private async Task<string> GetTitleAsync()
{
    await Task.Delay(3000);
    return "Hello!";
}

जैसे ही मैंने एप्लिकेशन चलाया, बटन पर क्लिक करना: "बटन 9" - एक डेड लॉक का कारण बना, (चूंकि थ्रेड ".result" पर लटका हुआ था)

GetTitleAsync() इस तरह लिखना:

private async Task<string> GetTitleAsync()
{
    await Task.Delay(3000).ConfigureAwait(false);
    return "Hello!";
}

गतिरोध हल किया - और आवेदन ठीक चला।

पर समझ नहीं आता कैसे ?

मुझे उम्मीद थी, कि ".ConfigureAwait(false)" का उपयोग करने से ऐसी स्थिति पैदा होगी जिसमें:

"बटन 9. टेक्स्ट = टेक्स्ट;" एक से भिन्न थ्रेड पर निष्पादित किया जाता है, जिस पर UI बनाया गया था, और एक अपवाद फेंक दिया जाएगा!

लेकिन यह उत्कृष्ट काम करता है! कैसे??

0
Eynat Sagiv 28 जिंदा 2021, 11:55
1
Async कोड पर ब्लॉक न करें - - .ConfigureAwait(false); को वहां से हटा दें, बदलें: private async void button9_Click और string text = await GetTitleAsync();
 – 
Jimi
28 जिंदा 2021, 12:02
ConfigureAwait(false); एक अलग थ्रेड पर निरंतरता को फिर से शुरू करने का कारण बनता है, लेकिन WindowsFormsSynchronizationContext मजबूत है, पहली प्रतीक्षा UI थ्रेड में फिर से शुरू होगी। तो Result करेंगे। लेकिन आप async कोड को ब्लॉक नहीं करते हैं।
 – 
Jimi
28 जिंदा 2021, 12:08
मैं इस विषय पर स्टीफन क्लेरी की पोस्ट पढ़ने की भी सलाह देता हूं (पहली टिप्पणी में लिंक)। मुझे इसे इस उत्तर में भी समझाना होगा: ConfigureAwait(false) UI डेडलॉक को कैसे रोकें। आपको यह उपयोगी लग सकता है।
 – 
Reza Aghaei
28 जिंदा 2021, 12:42

1 उत्तर

सबसे बढ़िया उत्तर

मुझे उम्मीद थी, कि ".ConfigureAwait(false)" का उपयोग करने से ऐसी स्थिति पैदा होगी जिसमें "button9.Text = text;" एक से भिन्न थ्रेड पर निष्पादित किया जाता है, जिस पर UI बनाया गया था, और एक अपवाद फेंक दिया जाएगा! लेकिन यह उत्कृष्ट काम करता है! कैसे??

मैं अपना async/awaitपरिचय पढ़ने की सलाह देता हूं; परिचय के लिए बहुत अधिक विस्तार में जाने के बिना, मैं async/await और उनके संदर्भों के बारे में जानने के लिए आवश्यक सभी चीजों को शामिल करने का प्रयास करता हूं।

विशेष रूप से, उस पोस्ट से दो बिंदु हैं जो ध्यान देने योग्य हैं:

  • प्रत्येक async विधि कॉलिंग थ्रेड पर समकालिक रूप से निष्पादित करना शुरू कर देती है।
  • await किसी संदर्भ को तब तक कैप्चर करता है जब तक कि आप ConfigureAwait(false) का उपयोग नहीं करते।

तो, इस कोड के माध्यम से चलना:

private void button9_Click(object sender, EventArgs e)
{
    string text = GetTitleAsync().Result;
    button9.Text = text;            
}

private async Task<string> GetTitleAsync()
{
    await Task.Delay(3000).ConfigureAwait(false);
    return "Hello!";
}

ऐसा होता है, क्रम में, विशेष ध्यान दिया जाता है कि कौन सा धागा किस कोड को चलाता है:

  1. button9_Click UI थ्रेड पर GetTitleAsync() कॉल करता है।
  2. GetTitleAsync() Task.Delay(3000) को कॉल करता है और 3 सेकंड में पूरा होने वाला कार्य वापस प्राप्त करता है।
  3. GetTitleAsync() ConfigureAwait(false) को कॉल करता है और एक कॉन्फ़िगर किया हुआ वेटर वापस प्राप्त करता है जो वर्तमान (UI) संदर्भ में फिर से शुरू नहीं होगा।
  4. GetTitleAsync() कार्य पूरा होने के लिए अतुल्यकालिक रूप से प्रतीक्षा करने के लिए await का उपयोग करता है। यह await वर्तमान (UI) संदर्भ में फिर से शुरू नहीं होगा क्योंकि await को कॉन्फ़िगर नहीं किया गया है।
  5. await कार्य की जांच करता है और देखता है कि यह पूरा नहीं हुआ है, इसलिए यह अपने कॉलर को अपूर्ण Task<string> लौटाता है।
  6. button9_Click उस कार्य पर .Result को कॉल करता है। यह UI थ्रेड को तब तक ब्लॉक करता है जब तक कि कार्य पूरा नहीं हो जाता (यानी, GetTitleAsync() निष्पादन समाप्त हो जाता है)।
  7. तीन सेकंड बाद, Task.Delay(3000) से लौटा हुआ कार्य पूरा होता है।
  8. GetTitleAsync() अपने await के बाद क्रियान्वित करना फिर से शुरू करता है। चूंकि यह एक कॉन्फ़िगर किया गया await था, यह थ्रेड पूल थ्रेड पर क्रियान्वित करना जारी रखता है।
  9. GetTitleAsync() रिटर्न "Hello!"। यह थ्रेड पूल थ्रेड पर किया जाता है।
  10. एक मान लौटाने से, GetTitleAsync() अब पूरा हो गया है, और Task<string> जो पहले लौटा था, अब परिणाम मान के साथ पूरा हो गया है। यह पूर्णता थ्रेड पूल थ्रेड पर भी होती है।
  11. चूंकि कार्य अब पूरा हो गया है, UI थ्रेड अब अवरुद्ध नहीं है, और यह button9_Click निष्पादित करना जारी रखता है।
  12. button9_Click UI थ्रेड पर button9.Text = text; निष्पादित करता है।
0
Stephen Cleary 28 जिंदा 2021, 17:03
आपके विस्तृत विवरण के लिए बहुत-बहुत धन्यवाद, यह मेरे लिए बहुत सम्मान की बात है! मैं आपके गहन ज्ञान और दया के लिए आपकी पूजा करता हूं।
 – 
Eynat Sagiv
1 फरवरी 2021, 16:02