this.Close()不会杀死观察者NewThreadScheduler.Default.Schedule

时间:2018-12-17 08:08:22

标签: c# multithreading system.reactive caliburn.micro

我对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类之一中进行订阅。我认为这并不重要,但以防万一...

1 个答案:

答案 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的代码,我本可以给您提供工作代码。

现在,要彻底关闭应用程序,您应该处理创建的所有订阅,但至少您不再需要在无限循环中占用线程。