4

Rx 2.0 の EventLoopScheduler を使用して、作業をキューに入れたりシリアル化したりしています。スケジューラーを破棄する必要があるときに、まだ作業が残っていると、未処理の ObjectDisposedException を受け取ります。これは予想される動作ですか?

考案/サンプルコード:

    EventLoopScheduler scheduler = new EventLoopScheduler();
    List<IDisposable> handles = new List<IDisposable>();

    for (int i = 0; i < 100; ++i)
    {
        var handle = Observable.Interval(TimeSpan.FromMilliseconds(1))
                               .ObserveOn(scheduler)
                               .Subscribe(Observer.Create<long>((x) => Thread.Sleep(1000)));

        handles.Add(handle);
    }

    Thread.Sleep(TimeSpan.FromSeconds(1));

    foreach (var handle in handles)
        handle.Dispose();

    scheduler.Dispose();
    Console.ReadLine();

スタックトレース:

   System.ObjectDisposedException
   at System.Reactive.Concurrency.EventLoopScheduler.Schedule[TState](TState state, TimeSpan dueTime, Func`3 action)
   at System.Reactive.Concurrency.LocalScheduler.Schedule[TState](TState state, Func`3 action)
   at System.Reactive.Concurrency.Scheduler.<>c__DisplayClass50`1.<InvokeRec1>b__4e(TState state2)
   at System.Reactive.ScheduledObserver`1.Run(Object state, Action`1 recurse)
   at System.Reactive.Concurrency.Scheduler.<>c__DisplayClass50`1.<InvokeRec1>b__4d(TState state1)
   at System.Reactive.Concurrency.Scheduler.InvokeRec1[TState](IScheduler scheduler, Pair`2 pair)
   at System.Reactive.Concurrency.ScheduledItem`2.InvokeCore()
   at System.Reactive.Concurrency.ScheduledItem`1.Invoke()
   at System.Reactive.Concurrency.EventLoopScheduler.Run()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

この未回答の質問に似ています: RX2.0: ObjectDisposedException after disposing EventLoopScheduler

4

3 に答える 3

3

作業が残っているということではありません (つまり、スケジューラのキューにまだ何かが残っている) のではなく、そのキューに何かを追加しようとしている未解決のサブスクリプションがまだ残っているということです。

すべてのサブスクリプションを破棄してからスケジューラを破棄すると、正しく動作するはずです

于 2013-03-28T19:32:13.077 に答える
2

ええ、私も以前にそれを見たことがあります-「イベントスレッドをフラッシュする」方法自体はないと思いますが、次のようなことができます:

EventLoopScheduler scheduler = new EventLoopScheduler();
var wrappedScheduler = scheduler.Catch<Exception>((ex) => 
{
    Console.WriteLine("Got an exception:" + ex.ToString());
    return true;
});

for (int i = 0; i < 100; ++i)
{
    var handle = Observable.Interval(TimeSpan.FromMilliseconds(1))
                           .ObserveOn(wrappedScheduler)
                           .Subscribe(Observer.Create<long>((x) => Thread.Sleep(1000)));

    handles.Add(handle);
}
于 2013-03-28T17:23:56.823 に答える