C# 为什么dispose在Scheduler.Default.Schedule()中不执行任何操作?

C# 为什么dispose在Scheduler.Default.Schedule()中不执行任何操作?,c#,system.reactive,dispose,C#,System.reactive,Dispose,我们正在使用.Net的ReactiveExtensions 我们计划代码在线程池上运行,如下所示: IDisposable myDisposable = Scheduler.Default.Schedule(() => { int count = 0; while (true) { Console.WriteLine(++count); Thread.Sleep(500); } }); Console.ReadKey();

我们正在使用.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??)来检查代码内部,以便及时终止其运行


谢谢

代码继续运行的原因是您希望Dispose()调用神奇地退出硬循环(while(true)部分)

您可以设置一个变量,并在dispose方法中取消设置该变量,例如:

_isRunning = true;
while(_isRunning)
{
    // do stuff
}
然后在dispose方法中,调用:

_isRunning = false;
我在这里的回答中发布了一种实现.Net任务调度的方法,这可能会有所帮助:

您面临的问题是,一旦线程进入
而(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));

简单。

您在哪里声明/设置
计划的
?计划程序上的计划代码与创建任务不同。运行时不能取消线程池上计划的操作;返回的一次性调用只会阻止该方法将来的递归调度调用。使任务和Rx正确交互的方法并不总是显而易见的,但在这种情况下,看起来您需要一个任务。(为此,您应该有一个
scheduleAncy
。@dymanoid谢谢我解决了它,复制错误paste@JeroenMostert但是我的代码是同步的,谢谢你的详细答案(你总是写很长的答案)。这对我来说不是一个解决方案,因为while(true)是一个非递归的长时间运行的阻塞代码的示例,所以我不能用“重新调度”解决方案重写它。根据您的回答,我理解从Schedule()返回的IDisposable对我来说是无用的。这就是我一直在寻找的答案。我仍然不太明白它的用途是什么???@Yitzchak-一次性的主要是用来取消重复的日程安排-就像我的第一个例子。嗨,谢谢你的回答。在我的真实代码中,我没有Dispose方法。我之所以使用isScheduler实现,是因为我可以在测试中模拟它,我想我可以使用它的Dispose来停止操作的运行。从您的回答中,我了解到从isScheduler.Schedule()返回的IDisposable在Scheduler.Default的情况下是无用的。这就是我的答案。