Как мне запустить Dispatcher.Invoke () в библиотеке классов. NET Core 3? - PullRequest
1 голос
/ 10 января 2020

Я разрабатываю приложение WPF / NetCore3.1 с MVVM. В представлении есть кнопка, которая связана с RelayCommand. ViewModel находится в другой библиотеке классов, чем View. В ViewModel запускается таймер, который каждую секунду увеличивает переменную и запускает событие CanExecuteChanged объекта RelayCommand.

Вот мой ViewModel:

public ImportExportViewModel()
{
    MakeOfferCommand = new RelayCommand(MakeOffer, CanMakeOffer);


    Timer t = new Timer(1000);
    t.Elapsed += T_Elapsed;
    t.Start();
}

private void T_Elapsed(object sender, ElapsedEventArgs e)
{            
    ElapsedTime++;

    MakeOfferCommand.RaiseCanExecuteChanged();
}

private void MakeOffer()
{
    // TODO Make Offer
}

private bool CanMakeOffer()
{
    return ElapsedTime < 60;
}

А вот RaiseCanExecuteChanged:

public void RaiseCanExecuteChanged()
{
    var handler = CanExecuteChanged;
    if (handler != null)
    {
        handler(this, new EventArgs());
    }
}

Но здесь я получаю InvalidOperationException: вызывающий поток не может получить доступ к этому объекту, потому что объект принадлежит другому потоку.

Обычно я выполняю здесь Dispatcher.Invoke (), но в .NetCore3.1 этого, похоже, нет.

Может кто-нибудь сказать мне, как я все еще могу делать вызовы между потоками?

1 Ответ

1 голос
/ 10 января 2020

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

Интерфейс:

public interface IDispatch
{
    bool CheckAccess();
    void Invoke(Action action);
}

Просмотреть модель :

public IDispatch Dispatch { get; set; }

private void T_Elapsed(object sender, ElapsedEventArgs e)
{
    if (Dispatch != null && !Dispatch.CheckAccess())
        Dispatch.Invoke(new Action(() => { /* do something */ }));
    ...
}

Реализация WPF:

public class WpfDispatch : IDispatch
{
    private readonly Dispatcher _dispatcher;

    public WpfDispatch(Dispatcher dispatcher) =>
        _dispatcher = dispatcher;

    public bool CheckAccess() => _dispatcher.CheckAccess();

    public void Invoke(Action action) => _dispatcher.Invoke(action);
}
...