this.Close () не уничтожает поток, созданный наблюдателем NewThreadScheduler.Default.Schedule - PullRequest
0 голосов
/ 17 декабря 2018

Я довольно новичок в C #, и у меня возникла следующая проблема: у меня есть приложение WPF, которое выполняет бесконечную задачу, которая выполняет некоторые довольно дорогие фоновые операции.Эти операции могут иногда изменять значение, и оно должно обновляться в пользовательском интерфейсе.Операции должны выполняться в потоке, отличном от потока пользовательского интерфейса, поскольку они могут заблокировать пользовательский интерфейс.Итак, я пытаюсь использовать библиотеку 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;
    });
}

Затем я подписываюсь на нее и изменяю значение, которое мне нужно обновить в пользовательском интерфейсе:

sevice.DoBackgroundOperations(param).Subscribe(newVal => Data = newVal);

Как я уже говорил, я получаю обновленные значения, когда они приходят, и они работают хорошо, но когда срабатывает событие нажатия кнопки закрытия, окно пользовательского интерфейса «исчезает», но само приложение никогда не закрывается.Я думаю, что поток, созданный наблюдаемой, поддерживает приложение в рабочем состоянии.

Итак, мой вопрос: как правильно закрыть приложение и не допустить его сохранения в потоке?

Спасибо!

Редактировать

Я использую caliburn.micro для реализации шаблона MVVM.Я делаю подписку в одном из моих классов ViewModel.Я не думаю, что это имеет значение, но на всякий случай ...

1 Ответ

0 голосов
/ 17 декабря 2018

Никогда не возвращай 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Я мог бы дать вам рабочий код.

Теперь, чтобы аккуратно закрыть ваше приложение, вы должны утилизировать любые созданные вами подписки, но, по крайней мере, вы больше не будете связывать поток в бесконечном цикле.

...