C#: MVC с контролами из фонового потока

187
09 января 2020, 19:50

Есть контроллер, который работает в отдельном потоке, т.к. на него вешается сетевая часть. В момент когда приходит сообщение от сервера, он создает объект в модели и вызывает событие. На событие подписан Вид. При вызове события отрисовывается модель. Проблема в том, что событие вызывается из другого потока, и метод из Вида соответственно тоже. Чтобы отрисовка происходила в нужном потоке, приходится на прямую обращаться к Виду, и вызывать у него метод Invoke().

В итоге получается, что контроллер полностью зависим от Вида. И практически в каждом методе контроллера встречается такой код:

view.Dispatcher.Invoke(() => { model.OnChange...(...); });

На сколько понял, Контроллер ни как не должен быть связан с Видом.

Вот собственно вопрос: "Как сделать правильно?". Может быть, я не правильно понимаю концепцию MVC?

На всякий случай добавлю, Вид собран на WPF.

Answer 1

1) Впервые вижу, чтобы View переводили как "Вид". Обычно его переводят как "Представление"

2) Для WPF самый подходящий паттерн - MVVM. MVC - это больше для WinForms

Теперь по коду. Вам не обязательно прокидывать view куда бы то ни было для доступа к диспетчеру. Чтобы этого избежать, вы легко можете использовать прокси объекты, например

Создадим интерфейс

public interface IUIInteraction
{
    void Invoke(Action action);
}

Реализация

public class UIInteraction : IUIInteraction
{
    public void Invoke(Action action)
    {
        Application.Current.Dispatcher.Invoke(action);
    }
}

Прокинем в контроллер

public class MyController
{
    IUIInteraction _ui;
    public MyController(IUIInteraction ui)
    {
        _ui = ui;
    }

    public void DoStuff()
    {
        _ui.Invoke(() => {/*......*/});
    }
}

Всё. Теперь контроллер имеет возможность выполнять код в UI потоке, но при этом он зависит от вашего интерфейса, а не от кода представления.

READ ALSO
getsockopt() и CSADDR_INFO на С#

getsockopt() и CSADDR_INFO на С#

Пытаюсь использовать getsockopt() c параметром SO_BSP_STATE, используя

117
sqlite-net-pcl C# как получить данные из определенного столбца из базы данных?

sqlite-net-pcl C# как получить данные из определенного столбца из базы данных?

у меня есть локальная база данных создал на основе этой статьи https://docsmicrosoft

147
EF Core. Skip & Take (Include)

EF Core. Skip & Take (Include)

Всем приветЕсть модель MainCategory, содержащая коллекцию Categories

120