为什么代码会产生ObjectDisposedException

时间:2018-05-17 14:06:58

标签: c# system.reactive rx.net

static void Main(string[] args)
{
    Observable.Using(() => new EventLoopScheduler(), els => Observable
            .Defer(() => Observable.Return(1))
            .SubscribeOn(els))
        .Subscribe();
    Console.ReadLine();
}

为什么上面的代码会产生ObjectDisposedException? SubscribeOn究竟是如何运作的?

更多详情:

//can't compile
class DataService : ObservableBase<Unit>
{
    protected override IDisposable SubscribeCore(IObserver<Unit> o) 
    {
        return Observable.Defer(() => Observable.Start(() => _httpClient.Get(...)))
            .RepeatWithDelay(TimeSpan.FromSeconds(1))
            .ObserveOn(SchedulerEx.Current)//observe back to event loop
            .Do(...)
            .Select(_ => Unit.Default)
            .Subscribe(o)
    }
}
class Controller 
{
    void Start()
    {
        _instance = Observable.Using(
            () => SchedulerEx.Create(), 
            els => _dataService.SubscribeOn(els));
    }
    void Stop()
    {
        _instance.Dispose();
    }
}
class SchedulerEx 
{
    [ThreadStatic]
    public static EventLoopScheduler Current;
    public EventLoopScheduler Create() 
    {
        var els = new EventLoopScheduler();
        els.Schedule(() => SchedulerEx.Current = els);
        return els;
    } 
}
static void Main() 
{
    var controller = kernel.Get<Controller>();
    controller.Start();
    controller.Stop();//throw if stop immediately
}

我想要实现的内容:在Windows服务应用程序中,我有多个DataService独立运行在他们自己的事件循环中,我可以回想一下当前的事件循环。

4 个答案:

答案 0 :(得分:4)

这就是椒盐卷饼:

  • Observable.Using与C#using语句类似:它在观察结束后处置IDisposable
  • Observable.Defer延迟运行包含的代码,直到订阅者订阅。
  • SubscribeOn根据传入的IScheduler指示observable应该订阅哪个线程。

我测试了以下内容,它也爆炸了:

static void Main(string[] args)
{
    Observable.Using(() => new EventLoopScheduler(), els => 
        Observable.Empty<int>()
            .SubscribeOn(els)
    )
        .Subscribe();
}

...所以Defer没有影响。

显然Using在调度程序被使用之前处置它。如果您将Observable.Empty(或Observable.Return)更改为未立即完成的内容(例如Observable.NeverObservable.Interval(TimeSpan.FromMilliseconds(100)).Take(2),则不会将其炸毁。

它似乎是EventLoopScheduler中的竞争条件错误:Observable.UsingEventLoopScheduler可能都试图调用Dispose,如果错误的首先到达那里,爆炸。

我建议删除Using

答案 1 :(得分:1)

试试这个:

gradle-wrapper.properties

答案 2 :(得分:0)

Observable.Using(() => new EventLoopScheduler(), 
            els => new AnonymousObservable<long>(o => els.Schedule(Unit.Default, (_, s) => source.Subscribe(o))));

最后,我通过上面的代码解决了这个问题。

答案 3 :(得分:-1)

因为.Using()而非常确定。在内部,它(最有可能)继续进行using () {}构造,隐含地调用.Dispose()。{/ p>