Skip to content

EventLoopScheduler: unexpected Exception after Dispose #286

@ghost

Description

When calling Dispose on an EventLoopScheduler, that has at least one item in its working queue, it will throw an ObjectDisposedException. The exception is thrown from its worker thread (which gives us no chance to catch it).

Code to reproduce the problem:

class Program
{
    public static void Main() {
        var event_stream = new Subject<string>();

        var subscription = Observable.Using(
            resourceFactory:    () => new EventLoopScheduler(),
            observableFactory:  scheduler => event_stream
                .ObserveOn(scheduler)
                .Do(LongRunningAction))
            .Subscribe();

        event_stream.OnNext("event 1");

        Thread.Sleep(TimeSpan.FromSeconds(1));
        subscription.Dispose(); // Scheduler is still busy!

        Console.ReadLine();
    }
    private static void LongRunningAction(string event_text) {
        Thread.Sleep(TimeSpan.FromSeconds(2));
        Console.WriteLine(event_text);
    }
}

I've opened a question at stackoverflow (containing a work-around) some time ago. The workaround does not seem to catch all possible cases - I still get this (unhandled) exception from time to time:

System.ObjectDisposedException: Cannot access a disposed object.
   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.<>c__DisplayClass50`1.<>c__DisplayClass52.<InvokeRec1>b__4f(IScheduler scheduler1, TState state3)
   at System.Reactive.Concurrency.ScheduledItem`2.InvokeCore()
   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()

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions