2017-10-23 3 views
4

私は、シミュレーション/ワークフロー/ゲームロジックエンジンとして最もよく記述できるものに取り組んでいます(これらのカテゴリのいずれにも該当しません)。非常に長いRxイベントチェーン

これは、完全にイベント駆動型(リアクティブ)であることを意図しており、分岐やフィルタリング、同時実行性、およびそのすべてのRxの良さを伴う数十万または数十万の連鎖イベントの可能性をサポートする必要があります。

私は非常に Reactive Extensionsには新しく、私が考えることができる最も簡単なテストを書くことに決めました(複数のISubjectsを連鎖させる)。私はすぐに一緒に連鎖することは、StackOverflowExceptionを引き起こす(私のケースでは約12000)イベントが多すぎることがわかりました.Rxがイベントハンドラを斬新な方法で結びつけていると考えると、コールスタックは深くしかできません。

だから私はこの制限を回避する(Reactive-ish?)方法を探しています。私は、この枠組みで非常に大きなことをしたい唯一の人になることはできません。コミュニティが提供できるあらゆる助けは大いに感謝されるでしょう。

は、ここに私のテストコードがあります:

class Program 
{ 
    static void Main(string[] args) 
    { 
     for (int i = 0; i < 1000000; i += 1000) 
     { 
      Console.Write($"{i} "); 
      using (Dynamite dynamite = new Dynamite()) 
      { 
       dynamite.Setup(i); 
       dynamite.Trigger(); 
      } 
     } 
     Console.ReadKey(); 

    } 
} 

public class Dynamite : IDisposable 
{ 
    ISubject<bool> start = null; 
    IList<IDisposable> handles = new List<IDisposable>(); 

    public void Setup(int length) 
    { 
     length = length == 0 ? 1 : length; 

     var fuses = 
      Enumerable.Range(0, length) 
      .Select(v => new Subject<bool>()) 
      .ToArray(); 

     ISubject<bool> prev = null; 

     foreach (var fuse in fuses) 
     { 
      //Console.Write("."); 

      if (prev != null) 
      { 
       Attach(prev, fuse); 
      } 
      prev = fuse; 
     } 

     start = fuses.First(); 
     var end = fuses.Last(); 

     handles.Add(
      end 
       .Subscribe(onNext: b => 
       { 
        //Console.Write("t"); 
        this.Explode(); 
       })); 
    } 

    void Attach(ISubject<bool> source, ISubject<bool> dest) 
    { 
     var handle = source 
      .Subscribe(onNext: b => 
      { 
       //Console.Write("s"); 
       dest.OnNext(b); 
      }); 
     handles.Add(handle); 
    } 

    public void Trigger() 
    { 
     //Console.Write("p"); 
     start.OnNext(true); 
    } 

    void Explode() 
    { 
     Console.WriteLine("...BOOM!"); 
    } 

    public void Dispose() 
    { 
     foreach (var h in handles) 
      h.Dispose(); 
    } 
} 

ここでコンソール出力です:

0 ...BOOM! 
1000 ...BOOM! 
2000 ...BOOM! 
3000 ...BOOM! 
4000 ...BOOM! 
5000 ...BOOM! 
6000 ...BOOM! 
7000 ...BOOM! 
8000 ...BOOM! 
9000 ...BOOM! 
10000 ...BOOM! 
11000 ...BOOM! 
12000 
Process is terminated due to StackOverflowException. 

答えて

0

私は解決策を見つけました。 CurrentThreadスケジューラ。

.ObserveOn(Scheduler.CurrentThread) 

CurrentThreadScheduler [...]オリジナルの呼び出しを行ったスレッド上で実行されるアクションをスケジュールします。アクションはすぐには実行されませんが、キューに配置され、現在のアクションが完了した後にのみ実行されます。

+0

これがどのように答えられるか説明できますか? – Enigmativity

+2

@Enigmativityシーケンス内の各操作はスケジュールされるため、同じCallStack内ですぐに実行されることはありません。これにより、StackOverFlowExceptionの発生を防ぐことができます。 – m1o2

+0

これは、パフォーマンスが大幅に低下する可能性があります。 – m1o2

関連する問題