为什么 dispose 在 Scheduler.Default.Schedule() 中什么都不做?
Why dispose does nothing in 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();
如您所见,这是 运行 在控制台应用程序上的测试代码。
当我配置预定代码时,代码保持运行ning!
我没有可以检查的标志,我无法添加 if 语句来自行停止预定代码。
谁能解释一下?如果它不起作用,为什么我会得到一个 IDisposable?以及为什么我没有得到某种标志(CancellationToken??)来检查我的代码,以便我可以及时终止它的 运行ning?
谢谢!
您的代码继续运行的原因是您期望 Dispose() 调用神奇地退出硬循环(while(true) 部分)。
您可以设置一个变量 - 并在您的 dispose 方法中取消设置该变量,例如:
_isRunning = true;
while(_isRunning)
{
// do stuff
}
然后在你的dispose方法中,调用:
_isRunning = false;
我在这里的回答中发布了一种实现 .Net 任务调度的方法,这可能会有所帮助:
Best way to create a "run-once" time delayed function in C#
您面临的问题是,一旦您的线程进入 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));
简单。
我们正在为 .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();
如您所见,这是 运行 在控制台应用程序上的测试代码。
当我配置预定代码时,代码保持运行ning!
我没有可以检查的标志,我无法添加 if 语句来自行停止预定代码。
谁能解释一下?如果它不起作用,为什么我会得到一个 IDisposable?以及为什么我没有得到某种标志(CancellationToken??)来检查我的代码,以便我可以及时终止它的 运行ning?
谢谢!
您的代码继续运行的原因是您期望 Dispose() 调用神奇地退出硬循环(while(true) 部分)。
您可以设置一个变量 - 并在您的 dispose 方法中取消设置该变量,例如:
_isRunning = true;
while(_isRunning)
{
// do stuff
}
然后在你的dispose方法中,调用:
_isRunning = false;
我在这里的回答中发布了一种实现 .Net 任务调度的方法,这可能会有所帮助: Best way to create a "run-once" time delayed function in C#
您面临的问题是,一旦您的线程进入 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));
简单。