मुझे await
कीवर्ड काम करता है, और मैं इसकी समझ को थोड़ा सा विस्तारित करना चाहता हूं, इसकी एक नाजुक समझ है।रिकर्सन और प्रतीक्षा/एसिंक कीवर्ड
जो मुद्दा अभी भी मेरे सिर स्पिन बनाता है वह रिकर्सन का उपयोग है। यहाँ एक उदाहरण है:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestingAwaitOverflow
{
class Program
{
static void Main(string[] args)
{
var task = TestAsync(0);
System.Threading.Thread.Sleep(100000);
}
static async Task TestAsync(int count)
{
Console.WriteLine(count);
await TestAsync(count + 1);
}
}
}
यह एक स्पष्ट रूप से एक StackOverflowException
फेंकता है।
मेरी समझ इसलिए है क्योंकि कोड वास्तव में पहली एसिंक्रोनस एक्शन तक सिंक्रनाइज़ेशन चलाता है, जिसके बाद यह Task
ऑब्जेक्ट देता है जिसमें एसिंक्रोनस ऑपरेशन के बारे में जानकारी होती है। इस मामले में, कोई एसिंक्रोनस ऑपरेशन नहीं है, इस प्रकार यह झूठे वादे के तहत अभी भी पुनरावर्ती रहता है कि इसे अंततः Task
वापस कर दिया जाएगा।
अब यह बदल रहा है सिर्फ एक छोटा सा:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestingAwaitOverflow
{
class Program
{
static void Main(string[] args)
{
var task = TestAsync(0);
System.Threading.Thread.Sleep(100000);
}
static async Task TestAsync(int count)
{
await Task.Run(() => Console.WriteLine(count));
await TestAsync(count + 1);
}
}
}
यह एक एक StackOverflowException
फेंक नहीं है। मैं सॉर्टोफ़ देख सकता हूं कि यह क्यों काम करता है, लेकिन मैं इसे अधिक आंत महसूस कर दूंगा (यह संभवत: इस बात से संबंधित है कि स्टैक बनाने से बचने के लिए कॉलबैक का उपयोग करने के लिए कोड कैसे व्यवस्थित किया जाता है, लेकिन मैं उस आंत को एक में महसूस नहीं कर सकता स्पष्टीकरण)
तो मैं दो प्रश्न हैं:
- कैसे कोड के दूसरे बैच एक
StackOverflowException
से बचने करता है? - क्या कोड का दूसरा बैच अन्य संसाधनों को बर्बाद करता है? (उदाहरण के लिए यह ढेर पर एक बड़ी संख्या में कार्य वस्तुओं को आवंटित करता है?)
धन्यवाद!
तो यदि मैंने एक कार्य के साथ 'कार्य.रुन()' को प्रतिस्थापित किया है जो तुरंत एक पूर्ण 'कार्य' ऑब्जेक्ट लौटाता है, तो यह स्टैक ओवरफ़्लो अपवाद को पुन: पेश करेगा? (या मैंने बस ऐसा कुछ प्रस्तावित किया जो संभव नहीं है?) – riwalk
@ Stargazer712 न केवल यह संभव है, यह वास्तव में वही करेगा जो आप वर्णन कर रहे हैं। बस 'टास्क का प्रयास करें। FromResult
@ Stargazer712 हां! और यदि आपने इसे 'टास्क.इल्ड() '(जिसे निरंतरता पोस्ट करने की आवश्यकता है) के साथ प्रतिस्थापित किया है तो आपको स्टैक ओवरफ़्लो (प्रदर्शन लागत पर) से गारंटी प्राप्त स्वतंत्रता प्राप्त होगी। ध्यान दें, कि 'यील्ड' 'कार्य 'के अलावा एक प्रतीक्षा योग्य लौटाता है। यह गारंटी किसी कार्य से प्राप्त करना बहुत कठिन है क्योंकि आपको यह सुनिश्चित करना होगा कि प्रतीक्षा सुविधा द्वारा पूछे जाने पर यह पूरा नहीं हुआ है। – usr