मैं एक सी # (.NET 4.5) एप्लिकेशन लिख रहा हूं जिसका उपयोग रिपोर्टिंग उद्देश्यों के लिए समय आधारित घटनाओं को एकत्रित करने के लिए किया जाता है। रीयलटाइम और ऐतिहासिक डेटा दोनों के लिए मेरी क्वेरी तर्क पुन: प्रयोज्य बनाने के लिए मैं प्रतिक्रियाशील एक्सटेंशन (2.0) और उनके IScheduler
आधारभूत संरचना (HistoricalScheduler
और दोस्तों) का उपयोग करता हूं।Observable.Generate() सिस्टम क्यों फेंक देता है। StackOverflowException?
उदाहरण के लिए, मान लेते हैं हम घटनाओं की एक सूची बना (कालक्रम के अनुसार छाँटे गए, पर वे समान हो सकते हैं!) जिसका केवल पेलोड उनका टाइमस्टैम्प IST और एक निश्चित अवधि के बफ़र्स भर में उनके वितरण जानना चाहता हूँ:
const int num = 100000;
const int dist = 10;
var events = new List<DateTimeOffset>();
var curr = DateTimeOffset.Now;
var gap = new Random();
var time = new HistoricalScheduler(curr);
for (int i = 0; i < num; i++)
{
events.Add(curr);
curr += TimeSpan.FromMilliseconds(gap.Next(dist));
}
var stream = Observable.Generate<int, DateTimeOffset>(
0,
s => s < events.Count,
s => s + 1,
s => events[s],
s => events[s],
time);
stream.Buffer(TimeSpan.FromMilliseconds(num), time)
.Subscribe(l => Console.WriteLine(time.Now + ": " + l.Count));
time.AdvanceBy(TimeSpan.FromMilliseconds(num * dist));
निम्नलिखित स्टैक ट्रेस के साथ एक System.StackOverflowException
में इस कोड परिणाम चल रहा है (पिछले 3 लाइनों सभी तरह है यह नीचे):
mscorlib.dll!System.Threading.Interlocked.Exchange<System.IDisposable>(ref System.IDisposable location1, System.IDisposable value) + 0x3d bytes
System.Reactive.Core.dll!System.Reactive.Disposables.SingleAssignmentDisposable.Dispose() + 0x37 bytes
System.Reactive.Core.dll!System.Reactive.Concurrency.ScheduledItem<System.DateTimeOffset>.Cancel() + 0x23 bytes
...
System.Reactive.Core.dll!System.Reactive.Disposables.AnonymousDisposable.Dispose() + 0x4d bytes
System.Reactive.Core.dll!System.Reactive.Disposables.SingleAssignmentDisposable.Dispose() + 0x4f bytes
System.Reactive.Core.dll!System.Reactive.Concurrency.ScheduledItem<System.DateTimeOffset>.Cancel() + 0x23 bytes
...
ठीक है, समस्या Observable.Generate()
के अपने प्रयोग से आने के लिए सूची के आधार पर लगता है आकार (num
) और शेड्यूलर की पसंद के बावजूद।
मैं क्या गलत कर रहा हूं? या अधिक आम तौर पर, IObservable
को IEnumerable
से अपने स्वयं के टाइमस्टैम्प प्रदान करने का पसंदीदा तरीका क्या होगा?
इस त्रुटि का सामना करने से पहले कितना बड़ा हो सकता है? साथ ही, यदि आप डीबगर में सिंगल-स्टेप करते हैं, तो त्रुटि देखने से पहले निष्पादित कोड की आखिरी पंक्ति क्या है? –
मेरे लिए, महत्वपूर्ण दहलीज ~ 'num = 51600' (रिलीज कॉन्फ़िगरेशन में, डीबग कॉन्फ़िगरेशन में थोड़ा कम) पर प्रतीत होता है। अवलोकन अनुक्रम पूरी तरह से बनाया गया प्रतीत होता है। मैं 'Observable.Generate()' के लिए lamdba अभिव्यक्तियों पर ब्रेकपॉइंट्स हिट कर सकता हूं। 'Console.WriteLine()' के अंतिम कॉल के बाद अपवाद फेंक दिया जाता है। –
समझें, यह सिर्फ एक अनुमान है, लेकिन यह संदिग्ध रूप से लगता है कि धारा प्रत्येक तत्व का निपटान करने की कोशिश कर रही है, और प्रत्येक तत्व धारा का निपटान करने का प्रयास कर रहा है। आप 'रद्द करें' या 'निपटान' के लिए अनिवार्य रूप से रिकर्सिव कॉल के साथ समाप्त होते हैं, जो आपके स्टैक को उड़ाता है (जिसका डिफ़ॉल्ट आकार 1 मेगाबाइट है)। मैं यह कहने के लिए 'अवलोकनयोग्य' के साथ पर्याप्त परिचित नहीं हूं कि यह क्यों हो रहा है। –