首页 > 解决方案 > 为什么 dispose 在 Scheduler.Default.Schedule() 中什么都不做?

问题描述

我们正在为 .Net 使用 ReactiveExtensions

我们安排代码在线程池上运行,如下所示:

IDisposable myDisposable = Scheduler.Default.Schedule(() =>
{
    int count = 0;
    while (true)
    {
        Console.WriteLine(++count);
        Thread.Sleep(500);
    }
});

Console.ReadKey();

myDisposable.Dispose(); // WHY THIS DO NOTHING?!?!

Console.ReadKey();

如您所见,这是在控制台应用程序上运行的测试代码。

当我处理预定的代码时,代码会继续运行!

我没有可以检查的标志,我无法添加 if 语句来自行停止计划的代码。

有人可以解释一下吗?如果 IDisposable 不起作用,为什么我会得到它?为什么我没有得到某种标志(CancellationToken??)来检查我的代码,以便我可以及时终止它的运行?

谢谢!

标签: c#system.reactivedispose

解决方案


您面临的问题是,一旦您的线程进入while (true)循环,它就会被困住并且永远不会结束。没有什么神奇的东西.Dispose()会停止线程。

实际上,在您调用之前,一次性已处理完毕.Dispose()。由于您使用了.Schedule仅在代码启动后立即处理订阅后才运行的重载。

您需要做的是使用支持重新调度的重载。幸运的是已经有一个了。试试这个代码:

IDisposable myDisposable = Scheduler.Default.Schedule(0, TimeSpan.Zero, (count, reschedule) =>
{
    Console.WriteLine(count);
    reschedule(count + 1, TimeSpan.FromSeconds(0.5));
});

这完全符合您的要求 - 它可以正确处理。

现在,话虽如此,您正在使用 Rx,所以您不妨只使用标准的可观察运算符。这也有效:

IDisposable myDisposable =
    Observable
        .Timer(TimeSpan.Zero, TimeSpan.FromSeconds(0.5))
        .Subscribe(count => Console.WriteLine(count));

简单的。


推荐阅读