ReactiveUI The calling thread cannot access this object because a different thread owns it

雨燕双飞 提交于 2019-12-06 15:58:32

Try this:

public TestViewModel()
{
    AsyncCommand = new ReactiveAsyncCommand();
    AsyncCommand.Subscribe(_ => IsBusy = true);

    AsyncCommand
        .RegisterAsyncFunction(x => 
         { Thread.Sleep(3000); return "Ok"; })
        .Subscribe(x => { IsBusy = false; });
}

Or even better:

ObservableAsPropertyHelper<bool> _IsBusy;
public bool IsBusy {
    get { return _IsBusy.Value; }
}

public TestViewModel()
{
    AsyncCommand = new ReactiveAsyncCommand();
    AsyncCommand
        .RegisterAsyncFunction(x => 
         { Thread.Sleep(3000); return "Ok"; })
        .Subscribe(x => { /* do a thing */ });

    AsyncCommand.ItemsInFlight
        .Select(x => x > 0 ? true : false)
        .ToProperty(this, x => x.IsBusy);
}

I assume that your ViewModel property is implemented similiar to this:

public TestViewModel ViewModel
{
    get { return (TestViewModel)DataContext; }
    set { DataContext = value; }
}

In that case, when you click button, lambda function from your RegisterAsyncFunction is called on non-UI thread. In IsBusy = false instruction ReactiveUI invokes ViewModel property which tries to get DataContext on non-UI thread, which causes InvalidOperationException.

If you bind your ViewModel to View in Xaml, then ViewModel property isn't called.

To fix this code you should use Dispatcher.Invoke to call IsBusy = false:

AsyncCommand
    .RegisterAsyncFunction(x => 
    {
        Application.Current.Dispatcher.Invoke(() =>IsBusy = true); 
        Thread.Sleep(3000); 
        return "Ok"; 
    })'
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!