WPF DependencyObject调用线程exception

我有以下代码创建一个临时文件夹,并使用FileSystemWatcher轮询添加到Location属性上的文件夹的文件,并将它们添加到列表: Pastebin上的Scratchdisk.cs 。 我们的想法是创建一个Scratchdisk对象,并让FFmpeg将video帧提取到其中,FileSystemWatcher在FFmpeg创建它们时构建这些文件的列表,该列表显示为我的UI绑定的DependencyObject。

我像这样绑定Scratchdisk对象:

 ...  

在实际创建对象时,我得到以下exception:

 A first chance exception of type 'System.InvalidOperationException' occurred in WindowsBase.dll Additional information: The calling thread cannot access this object because a different thread owns it. 

在第28行get { return (List)GetValue(FileListProperty); } get { return (List)GetValue(FileListProperty); }

我想我需要一个Dispatcher.Invoke,但我不知道在哪里,我不知道第二个线程在哪里创建。 我假设它与FileSystemWatcher写入文件列表有关。

有帮助吗?

谢谢!

我访问它的方式是这样的。 它获取UI线程的调度程序

 System.Windows.Application.Current.Dispatcher.Invoke( (Action)(() => { //Access the UI from here })); 

在我所拥有的内容和你在评论中列出的内容之间要注意的主要事情是,无论你是在后面的代码,视图模型,服务类,无论在哪里,我都会工作。 并非所有项目都有Dispatcher ,因此this.Dispatcher并不总是有效。

您可以将调用包装在从Dispatcher调用的Action()中,如下所示:

 this.Dispatcher.BeginInvoke(new Action(() => { // your code accessing UI elements here })); 

虽然这是一个相当古老的线索,但我想暗示任何碰到我做过同样事情的人。 这是一个故意冗长的描述,因此搜索引擎可以找到下一个遇到这种模糊行为的人/ gal。

获取此处描述的SetValue / GetValue编译错误后,我需要从DependencyObject派生我的VM。

我想继续从我们的ViewModelBase派生我的VM,它来自我们的AbstractNotifyPropertyChanged类(当然不能从C#中的2个完整类派生)。 作为我的超级聪明人,我想我会将DependencyObject派生添加到我的AbstractNotifyPropertyChanged类。 我看不出为什么这个小小的改变会产生任何不利影响。 很多周,应用程序运行正常。

总有一个大毛茸茸的“然而”。 在测试期间,我发现当我选择一个项目时,我的一个combobox架崩溃了整个应用程序。 这是由于未处理的InvalidOperationException。 “调用线程无法访问此对象,因为不同的线程拥有它。” 使这个combobox不同的唯一因素是它将DependencyProperty用于某些值。

四天令人沮丧的调试无处可去,因为我的代码都没有拨打电话。 这一切都来自WPF,并且在调用堆栈到达GetValue中的 VerifyAccess时爆炸 。 显然,当它被框架调用时,尝试调用Invoke来交叉线程是不是会发生? 你会在哪里拨打Invoke电话?

由于正常调试失败,我不得不采取艰难的方式。 我回溯了我的签入步骤以找到代码的最后一次工作。 我已经知道它与combobox的DependencyProperty有某种关系,因此看到代码发生了变化,我的怀疑指向了DependencyObject派生。

在对代码派生进行一些处理以从我的所有ViewModel(通过ViewModelBase)的链中删除DependencyObject,并将该派生仅放置在我需要它的确切位置之后,问题已经解决了。