報告目的で時間ベースのイベントを集計するために使用されるC#(.NET 4.5)アプリケーションを作成しています。私のクエリロジックをリアルタイムデータと履歴データの両方で再利用できるようにするには、Reactive Extensions(2.0)とインフラストラクチャIScheduler
(HistoricalScheduler
とフレンド)を使用します。例えばObservable.Generate()がSystem.StackOverflowExceptionをスローするのはなぜですか?
、我々は(年代順にソートされたが、彼らは一致していてもよい!)、その唯一のペイロードそのタイムスタンプイストや固定期間のバッファ間でその分布を知りたいイベントのリストを作成すると仮定します
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));
次のスタックトレース(すべての方法ダウンし最後の3行をit's)とSystem.StackOverflowException
にこのコードの結果を実行:
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]を、問題がObservable.Generate()
の私の使用から来ているようだ、リストに応じて、サイズ(num
)、スケジューラの選択にかかわらず。
私は間違っていますか?または、より一般的には、IEnumerable
のイベントから独自のタイムスタンプを提供するIObservable
を作成するにはどうすればよいでしょうか?
このエラーが発生する前に、どのくらいの大きさの数値を入力できますか?また、デバッガでこれをシングルステップ実行すると、エラーが表示される前に実行される最後のコード行は何ですか? –
私にとっては、クリティカルなしきい値は〜num = 51600であるようです(リリース構成では、デバッグ設定で少し下回ります)。観測可能なシーケンスは完全に作成されたようです。私は 'Observable.Generate()'のlamdba式でブレークポイントを打つことができます。例外は 'Console.WriteLine()'の最後の呼び出しの後にスローされます。 –
これは単なる推測ですが、ストリームが各要素を破棄しようとしていて、各要素がストリームを破棄しようとしているように見えます。基本的に再帰的に 'Cancel'や' Dispose'を呼び出し、スタックを吹き飛ばします(デフォルトサイズは1メガバイトです)。私はなぜこれが起こっているのかを知るために「Observable」と十分に精通していない。 –