0

私はこれをやっている場所と呼ばれるメソッドを持ってSubscribe()います:-

private void Subscribe(){
            IObservable<long> timer = Observable.Interval(TimeSpan.FromMilliseconds(250), Scheduler.NewThread);
            IConnectableObservable<long> TimerPublisher = timer.Publish();
            TimerPublisher.Connect();

            this.DisposeMonsterAction = TimerPublisher.Subscribe(tick => MonsterAction());

            var timer = from tick in world.TimerPublisher where tick % 1 == 0 select tick;
            this.DisposeMonstersDeath = timer .Subscribe(tick => MonstersDeath());
}

MonsterAction()250msごとMonsterDeathに呼び出され、1 秒ごとに呼び出されますが、250ms ごとMonsterDeathに呼び出されるようには機能しません。この問題を解決するにはどうすればよいですか?

4

2 に答える 2

0

ここで「ホット」オブザーバブルを使用している理由は完全にはわかりませんが (おそらく他のコードが原因でしょうか?)、このように 2 つの離散時間ストリームを組み合わせる最も簡単な方法は次のMergeとおりです。

Action MonsterAction = 
    () => Console.WriteLine("MonsterAction");
Action MonsterDeath = 
    () => Console.WriteLine("MonsterDeath");

// action stream
var monsterAction = Observable
    .Interval(TimeSpan.FromMilliseconds(250))
    .Do(_ => MonsterAction());

// death stream
var monsterDeath = Observable
    .Interval(TimeSpan.FromMilliseconds(1000))
    .Do(_ => MonsterDeath());

// act, act, act, act + die, act, act, ...
var obs = monsterAction.Merge(monsterDeath);

// "warm up" the cold observable
var hotObs1 = obs.Publish();

using(var conn = hotObs1.Connect())
using(var x = hotObs1.Subscribe(evt => Console.WriteLine(evt)))
{
    Console.ReadLine();
}
于 2013-01-17T19:20:49.260 に答える
0

間隔シーケンスのかなり奇妙な共有と NewThread の使用を無視すると、あなたの問題は真っ向から横たわっているようです

where tick % 1 == 0

読む必要があるとしか想像できない

where tick % 4 == 0 //or ==3 or whatever...

つまり、integer/long 値を 1 で割ると余りが 0 になるため、where 句は意味がありません。

役立つその他のヒント:

  1. サブスクリプションを接続の前に置きます。つまり、Connectable オブザーバブルを引き続き使用する場合は、メソッドの最後の行として .Connect() 行を置きます。
  2. テストできるように、使用しているスケジューラに注入することを検討してください
  3. Task または ThreadPool スケジューラの使用を検討してください。単純なタイマー/インターバル スケジューリングには適しています。NewThread は、この仕事にとって大きなハンマーのように思えます。
  4. パラメータを使用していないことを示すには、_ 文字を使用します。たとえば、MonsterAction() を呼び出す Action と MonsterDeath を (_=>MonsterAction()) に変更できます。これは、実際にはパラメーターを使用しないことを次の開発者に示します。
  5. DisposeMonsterAction/DisposeMonstersDeath の名前を MonsterActionSubscription & MonstersDeathSubscription に変更します。
  6. シーケンスを共有しても何も得られないと思います。内部で実際に作業を行っているのはスケジューラです。実際には、値を 1 秒間に 4 回チェックすると、2 つのシーケンスを使用するよりも多くのコストがかかると想像できます。

あなたの仲間のチームメイト(将来のあなたを含む)のために、これはあなたのニーズに十分にシンプルであることをお勧めします

private void Subscribe(IScheduler timerScheduler){
    this.DisposeMonsterAction = Observable.Interval(TimeSpan.FromMilliseconds(250), timerScheduler).Subscribe(_ => MonsterAction());
    this.DisposeMonstersDeath = Observable.Interval(TimeSpan.FromMilliseconds(1000), timerScheduler).Subscribe(_ => MonstersDeath());
}

または名前を変更して

private void Subscribe(IScheduler timerScheduler){
    this.MonsterActionSubscription = Observable.Interval(TimeSpan.FromMilliseconds(250), timerScheduler).Subscribe(_ => MonsterAction());
    this.MonstersDeathSubscription = Observable.Interval(TimeSpan.FromMilliseconds(1000), timerScheduler).Subscribe(_ => MonstersDeath());
}
于 2013-01-22T12:28:23.383 に答える