ReactiveUI WPF - вызывающий поток не может получить доступ к этому объекту, потому что он принадлежит другому потоку

Спасибо @GlennWatson за указание на то, что мне нужно добавить ссылку на пакет Nuget ReactiveUI.WPF в дополнение к пакету ReactiveUI.

У меня есть модель представления ReactiveObject, в которой я хотел бы использовать OpenFileDialog для установки значения одного из свойств моей модели представления (PdfFilePath). Все, что я пробовал, приводит к ошибке The calling thread cannot access this object because a different thread owns it.

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

public class ImportPdfViewModel : ReactiveObject
{
    public ImportPdfViewModel()
    {
        SelectFilePathCommand = ReactiveCommand.Create(() =>
        {
            OpenFileDialog ofd = new OpenFileDialog() { };
            //
            if (ofd.ShowDialog() == DialogResult.OK)
                PdfFilePath = ofd.FileName;
        });
    }

    private string _PdfFilePath;
    public string PdfFilePath
    {
        get => _PdfFilePath;
        set => this.RaiseAndSetIfChanged(ref _PdfFilePath, value);
    }

    public ReactiveCommand SelectFilePathCommand { get; set; }
}

Как я уже упоминал, я пробовал множество различных вариантов, включая внедрение службы в мою модель представления, но независимо от того, где я создаю экземпляр OpenFileDialog (например, в основном представлении), я всегда получаю одну и ту же ошибку.

Я также чертовски погуглил "ReactiveUI" и "OpenFileDialog", но ни один из найденных мной кодов не выглядит актуальным (например, с использованием ReactiveCommand<Unit, Unit>) и не согласуется с каким-либо другим примером! Спасибо.


ОБНОВИТЬ

Спасибо @GlennWatson за указание на то, что мне нужно добавить ссылку на пакет Nuget ReactiveUI.WPF в дополнение к пакету ReactiveUI.

Как только я его добавил, код заработал!

Теперь код выглядит так, я считаю, что он совместим с MVVM, использует внедрение зависимостей и использует последние функции / лучшие практики ReactiveUI (хотя я, очевидно, открыт для критики!):

ImportPdf

public class ImportPdfViewModel : ReactiveObject
{
    public ImportPdfViewModel(IIOService openFileDialogService)
    {
        SelectFilePathCommand = ReactiveCommand
            .Create(() => openFileDialogService.OpenFileDialog(@"C:\Default\Path\To\File"));
        SelectFilePathCommand.Subscribe((pdfFilePath) => { PdfFilePath = pdfFilePath; });
    }

    private string _PdfFilePath;
    public string PdfFilePath
    {
        get => _PdfFilePath;
        set => this.RaiseAndSetIfChanged(ref _PdfFilePath, value);
    }

    public ReactiveCommand<Unit, String> SelectFilePathCommand { get; set; }
}

IIOService

public interface IIOService
{
    string OpenFileDialog(string defaultPath);
}

OpenFileDialogService

public class OpenFileDialogService : IIOService
{
    public string OpenFileDialog(string defaultPath)
    {
        OpenFileDialog ofd = new OpenFileDialog() { FileName = defaultPath };
        //
        if (ofd.ShowDialog() == DialogResult.OK)
        {
            return ofd.FileName;
        }
        else
        {
            return null;
        }
    }
}

ОБНОВИТЬ

У меня также была указанная ниже ошибка, вызванная тем же отсутствующим пакетом ... This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread

Часто решение такой проблемы состоит в том, чтобы заключить строку, вызывающую проблему, в Application.Current.Dispatcher.Invoke ().

Robin Bennett 06.11.2018 12:10

@RobinBennett Спасибо за ваш комментарий ... однако во время моего Googleathon я наткнулся на этот комментарий (в конце сообщения) Пола Беттса, автора ReactiveUI, который сказал, что это неправильный способ делать это! stackoverflow.com/a/16596310/5040941. Я просто не могу понять, как экстраполировать его фактический ответ (выше этого сообщения), чтобы он соответствовал моему сценарию. Кроме того, его ответ датирован 2013 годом, и у меня сложилось впечатление, что ReactiveUI достаточно изменился, и теперь есть более эффективные способы.

3-14159265358979323846264 06.11.2018 12:16

Достаточно справедливо - я должен был упомянуть, что ничего не знаю о ReactiveUI!

Robin Bennett 06.11.2018 12:18

: 0) ты не единственный \ 0 / !!

3-14159265358979323846264 06.11.2018 12:19

На какой платформе вы работаете? У вас часто возникают проблемы с потоковой передачей, если вы не включаете нужные пакеты NuGet. Например, reactiveui.wpf

Glenn Watson 06.11.2018 12:22

Избегайте абстрактного базового класса. Используйте ReactiveCommand <Unit, Unit>

Glenn Watson 06.11.2018 12:24

@GlennWatson. Просто добавил ссылку на пакет nuget reactiveui.wpf, и он сразу заработал! Если вы измените свой комментарий на ответ, я сразу его приму!

3-14159265358979323846264 06.11.2018 12:31

Боже мой, я просто ударил головой из-за этого. Слава богу за этот вопрос и ответ.

JMIII 24.06.2019 22:25
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
8
618
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы работаете на платформе WPF или WinForms, вам необходимо убедиться, что вы включили ссылку nuget на ReactiveUI.WPF или ReactiveUI.Winforms.

Еще раз спасибо, Гленн. Я выделил это в начале своего вопроса, потому что кажется, что это может исправить гораздо больше, чем мою проблему с OpenFileDialog! : 0)

3-14159265358979323846264 14.11.2018 12:19

Другие вопросы по теме