允许从后台线程访问DispatcherObject

本文关键字:访问 DispatcherObject 线程 后台 | 更新日期: 2023-09-27 17:51:12

我以为我理解DispatcherObject是如何工作时,阅读一些教程,但困惑时,我使用它。这是我的程序:

namespace DispatcherObjectDemo
{
    public partial class MainWindow : Window
    {
        Foo foo;
        public MainWindow()
        {
            InitializeComponent();
            this.foo = new Foo();
        }
        private void Parallel(object sender, RoutedEventArgs e)
        {
            Task task = new Task(() => ChangeFoo());
            task.Start();
        }
        private void ChangeFoo()
        {
            // Protect from accessing to foo in background thread
            if (this.foo.CheckAccess())
            {
                this.foo = new Foo();
            }
        }
    }
    public class Foo : DispatcherObject
    {
        public string Name
        { 
            get; 
            set; 
        }
    }
}

所以这个想法是为了保护对foo对象的访问。CheckAccess()作为描述符,防止给foo对象分配新的引用。我的理解是,如果我不保护我的代码,我将有InvalidOperationException。

但是当我把它移开试一试时,它正常工作,没有任何异常。

private void ChangeFoo()
{
    this.foo = new Foo();
}

允许从后台线程访问DispatcherObject

呼叫

private void ChangeFoo()
{
    this.foo = new Foo();
}
任务池线程上的

不应该抛出任何异常。您只需创建一个新对象并将其分配给一个字段。

您指的是InvalidOperationException,如果在非调度线程的线程上调用该方法,则对DispatcherObject.VerifyAccess的调用将抛出InvalidOperationException,这是正确的。然而,调用new Foo()将不会调用VerifyAccess,所以您不会得到异常。

如果你想让"invalid"代码抛出异常,你应该调用VerifyAccess而不是CheckAccess

谢谢。但是线程亲和性呢?

…这被称为线程关联,意味着您只能使用WPF对象创建在其上的线程上。在其他地方使用线程将导致抛出运行时异常…

我的理解是在UI线程下创建的WPF对象只能在UI线程下使用,从后台线程调用它们会抛出异常。