【问题标题】:this.Close() not killing thread created by observer NewThreadScheduler.Default.Schedulethis.Close() 不会杀死观察者 NewThreadScheduler.Default.Schedule 创建的线程
【发布时间】:2018-12-17 08:08:21
【问题描述】:

我是 C# 的新手,遇到以下问题:我有一个 WPF 应用程序,它执行一个无限任务,该任务执行一些非常昂贵的后台操作。这些操作有时会更改值,并且必须在 UI 中进行更新。这些操作需要在不同于 UI 线程的线程中运行,因为它们可能会锁定 UI。所以,我正在尝试使用 System.Reactive 库,它实际上工作得很好......但是,当我尝试使用执行 this.Close(); 方法的自定义关闭按钮来关闭应用程序时,应用程序不是关闭。

我的 observable 看起来像这样:

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);

正如我之前所说,当更新值到来时我会收到更新的值并且它运行良好,但是当触发关闭按钮的单击事件时,UI 窗口“消失”但应用程序本身永远不会被关闭。我认为 observable 创建的线程使应用程序保持活力。

所以,我的问题是:如何正确关闭应用程序并防止线程保持活动状态?

谢谢!

编辑

我正在使用 caliburn.micro 来实现 MVVM 模式。我正在我的一个 ViewModel 类中进行订阅。我认为这并不重要,但以防万一......

【问题讨论】:

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


    【解决方案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 的代码,我可以给你工作代码。

    现在,要干净利落地关闭您的应用,您应该处置您创建的所有订阅,但至少您不会再将线程捆绑在无限循环中。

    【讨论】:

    • 感谢您的回答! “操作”实际上是读取和分析文件系统中的几个文件。根据这些文件的内容,观察者可以将新参数发送到 ViewModel,以便它可以更新 UI。
    • 为简单起见,我们总是可以将其简化为Thread.Sleep(3000); o.onNext("newParam");
    • Observable.Generate 非常强大。在可能的情况下,它可以代替Observable.Create 学习和使用。
    猜你喜欢
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 2019-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-05
    相关资源
    最近更新 更多