Zaman tabanlı olayları raporlama amacıyla toplamak için kullanılan bir C# (.NET 4.5) uygulaması yazıyorum. Sorgulama mantığımı hem gerçek zamanlı hem de geçmiş veriler için yeniden kullanılabilir hale getirmek için Reaktif Uzantılar (2.0) ve bunların IScheduler
altyapısını (HistoricalScheduler
ve arkadaşları) kullanıyorum.Neden Observable.Generate() System.StackOverflowException?
Örneğin, olayların bir listesini oluşturmak varsayalım (kronolojik ama çakışabilir!) Kendilerine ait yük onların damgası ist ve sabit süreli tampon göre dağılımlarını bilmek istiyorum:
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));
aşağıdaki yığın izleme ile System.StackOverflowException
bu kod sonuçları Running (aşağı son 3 çizgileri tüm yol İt's):
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
...
Tamam, sorun listeye bağlı olarak, Observable.Generate()
benim kullanımı geliyor gibi görünüyor boyut ()) ve programlayıcı seçiminden bağımsız olarak.
Neyi yanlış yapıyorum? Veya daha genel olarak, kendi zaman damgalarını sağlayan bir IEnumerable
olayından IObservable
oluşturmak için tercih edilen yol ne olurdu?
Bu hatayla karşılaşmadan önce num 'ne kadar büyük olabilir? Ayrıca, hata ayıklayıcısında bunu tek adımda atarsanız, hatayı görmeden önce yürüten son kod satırı nedir? –
Bana göre, kritik eşik = "num = 51600" değerinde görünüyor (Sürüm yapılandırmasında, Debug yapılandırmasında biraz daha az). Gözlenebilir sekans tamamen yaratılmış gibi görünüyor. Observable.Generate() 'için lamdba ifadelerinde kesme noktalarına vurabilirim. Son durum, Console.WriteLine() 'son çağrısından sonra atılır. –
Anlayın, bu sadece bir tahmindir, ancak akış her elemanın atmaya çalıştığından kuşkusuz gözüküyor ve her eleman akışı elden geçirmeye çalışıyor. Sonunda, 'İptal' veya 'Atma' için temel olarak özyinelemeli çağrılar ile sonuçlanırsınız, bu da yığınınızı (varsayılan boyutu 1 megabayttır) üfler. Bunun neden olduğunu söylemek için 'Gözlenebilir' ile yeterince tanıdık değilim. –