首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ReactiveUI调用线程无法访问此对象,因为另一个线程拥有它

ReactiveUI调用线程无法访问此对象,因为另一个线程拥有它
EN

Stack Overflow用户
提问于 2013-05-17 01:59:14
回答 2查看 2K关注 0票数 2

如果我在后台代码中使用绑定,则在change IsBusy处单击后会出现错误

代码语言:javascript
复制
"The calling thread cannot access this object because a different thread owns it"

xaml:

代码语言:javascript
复制
<Button x:Name="AsyncCommand"
                    Height="20"
                    Content="PushAsync"/>
<ProgressBar x:Name="IsBusy"
              Height="20"/>

政务司司长:

代码语言:javascript
复制
this.Bind(ViewModel, x => x.IsBusy, x => x.IsBusy.IsIndeterminate);
this.BindCommand(ViewModel, x => x.AsyncCommand, x => x.AsyncCommand);

视图模型:

代码语言:javascript
复制
public class TestViewModel : ReactiveObject
    {
        public TestViewModel()
        {
            AsyncCommand = new ReactiveAsyncCommand();
            AsyncCommand
                .RegisterAsyncFunction(x => 
                 { IsBusy = true; Thread.Sleep(3000); return "Ok"; })
                .Subscribe(x => { IsBusy = false; });
        }

        private bool isBusy;

        public bool IsBusy
        {
            get { return isBusy; }
            set { this.RaiseAndSetIfChanged(x => x.IsBusy, ref isBusy, value); }
        }
        public ReactiveAsyncCommand AsyncCommand { get; protected set; }
    }

但是如果我在xaml中进行绑定,所有的工作都是这样的:

政务司司长:

代码语言:javascript
复制
DataContext = new TestViewModel();

xaml:

代码语言:javascript
复制
<Button x:Name="AsyncCommand"
                    Height="20"
                    Content="PushAsync"
                    Command="{Binding AsyncCommand}"/>
<ProgressBar x:Name="IsBusy"
              Height="20"
              IsIndeterminate="{Binding IsBusy}"/>

为什么会发生这种情况?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-05-17 04:40:22

试试这个:

代码语言:javascript
复制
public TestViewModel()
{
    AsyncCommand = new ReactiveAsyncCommand();
    AsyncCommand.Subscribe(_ => IsBusy = true);

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

或者更好:

代码语言:javascript
复制
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);
}
票数 2
EN

Stack Overflow用户

发布于 2013-05-17 03:56:03

我假设您的ViewModel属性的实现方式与此类似:

代码语言:javascript
复制
public TestViewModel ViewModel
{
    get { return (TestViewModel)DataContext; }
    set { DataContext = value; }
}

在这种情况下,当您单击按钮时,将在非UI线程上调用RegisterAsyncFunction中的lambda函数。在IsBusy = false指令中,ReactiveUI调用ViewModel属性,该属性试图在非UI线程上获取DataContext,这会导致InvalidOperationException

如果在Xaml中将ViewModel绑定到View,则不会调用ViewModel属性。

要修复此代码,应使用Dispatcher.Invoke调用IsBusy = false

代码语言:javascript
复制
AsyncCommand
    .RegisterAsyncFunction(x => 
    {
        Application.Current.Dispatcher.Invoke(() =>IsBusy = true); 
        Thread.Sleep(3000); 
        return "Ok"; 
    })'
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16594339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档