我对C#相当陌生,并且遇到以下问题:我有一个WPF应用程序,该应用程序执行无限任务,该任务执行一些非常昂贵的后台操作。这些操作有时会更改值,并且必须在UI中进行更新。这些操作需要在与UI线程不同的线程中运行,因为它们可以锁定UI。因此,我试图使用System.Reactive库,并且实际上运行良好。但是,当我尝试使用执行this.Close();
方法的自定义关闭按钮来关闭应用程序时,该应用程序没有被关闭。
我的观察结果看起来像这样:
internal IObservable<string> DoBackgroundOperations(string param) {
return Observable.Create<string>(o => {
NewThreadScheduler.Default.Schedule(() => {
for (;;) {
param = // some operations that change the param
// when the param has been changed, I send the new value to the subscribers
o.OnNext(param);
}
});
return Disposable.Empty;
});
}
然后我要订阅它并更改需要在UI中更新的值:
sevice.DoBackgroundOperations(param).Subscribe(newVal => Data = newVal);
正如我之前说的,当更新值出现并且运行良好时,我会收到它们,但是当触发关闭按钮的click事件时,UI窗口“消失”,但是应用程序本身从未关闭。我认为可观察对象创建的线程使应用程序保持活动状态。
所以,我的问题是:如何正确关闭应用程序并防止线程保持活动状态?
谢谢!
我正在使用caliburn.micro来实现MVVM模式。我正在我的ViewModel类之一中进行订阅。我认为这并不重要,但以防万一...
答案 0 :(得分:1)
永远不要返回Disposable.Empty
。您之所以被迫这样做,是因为您创建了无限循环,因此代码又没有自然的可处理性。
摆脱无限循环,可以解决整个问题。
您可以通过以下方法简单地解决此问题:
internal IObservable<string> DoBackgroundOperations(string param)
{
return
Observable
.Generate(
0,
x => true,
x => x + 1,
x => /* some operations that change the param */,
Scheduler.Default);
}
我之所以选择Scheduler.Default
是因为Scheduler.NewThread
已过时。
如果您提供了// some operations that change the param
的代码,我本可以给您提供工作代码。
现在,要彻底关闭应用程序,您应该处理创建的所有订阅,但至少您不再需要在无限循环中占用线程。