Tôi đang viết một ứng dụng C# (.NET 4.5) được sử dụng để tổng hợp các sự kiện dựa trên thời gian cho mục đích báo cáo. Để làm cho logic truy vấn của tôi có thể tái sử dụng cho cả dữ liệu lịch sử và thời gian thực, tôi sử dụng Tiện ích mở rộng phản ứng (2.0) và cơ sở hạ tầng IScheduler
(HistoricalScheduler
và bạn bè của mình).Tại sao Observable.Generate() ném System.StackOverflowException?
Ví dụ, giả sử chúng ta tạo ra một danh sách các sự kiện (được sắp xếp thứ tự thời gian, nhưng họ có thể trùng!) Có tải trọng chỉ ist timestamp của họ và muốn biết phân phối của họ qua bộ đệm của một khoảng thời gian cố định:
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));
chạy mã này kết quả trong một System.StackOverflowException
với stack trace sau (Nó rất 3 dòng cuối cùng tất cả các con đường xuống):
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
...
Ok, vấn đề dường như đến việc sử dụng của tôi Observable.Generate()
, tùy thuộc vào danh sách kích thước (num
) và bất kể việc chọn lịch biểu.
Tôi đang làm gì sai? Hoặc nói chung, cách nào là cách ưa thích để tạo một số IObservable
từ một sự kiện IEnumerable
của các sự kiện cung cấp dấu thời gian của riêng họ?
Mức độ lớn hơn có thể là trước khi bạn gặp phải lỗi này? Ngoài ra, nếu bạn thực hiện một bước trong trình gỡ lỗi, dòng mã cuối cùng sẽ thực thi trước khi bạn thấy lỗi là gì? –
Với tôi, ngưỡng quan trọng có vẻ là ~ 'num = 51600' (trong cấu hình Release, ít hơn một chút trong cấu hình Debug). Chuỗi quan sát dường như được tạo ra hoàn toàn. Tôi có thể nhấn breakpoint tại các biểu thức lamdba cho 'Observable.Generate()'. Ngoại lệ được ném sau cuộc gọi cuối cùng đến 'Console.WriteLine()'. –
Hiểu, đây chỉ là phỏng đoán, nhưng có vẻ như đáng ngờ như luồng đang cố gắng vứt bỏ từng phần tử và mỗi phần tử đang cố gắng xử lý luồng. Bạn kết thúc với những gì cơ bản là đệ quy các cuộc gọi đến 'Hủy bỏ' hoặc' Vứt bỏ', mà thổi ngăn xếp của bạn (kích thước mặc định trong đó là 1 megabyte). Tôi không quen thuộc với 'Quan sát 'để nói tại sao điều này lại xảy ra. –