【问题标题】:WPF DependencyObject calling thread exceptionWPF DependencyObject 调用线程异常
【发布时间】:2014-11-23 16:33:44
【问题描述】:

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

我正在像这样绑定到 Scratchdisk 对象:

<ItemsControl ItemsSource="{Binding Source=ThumbnailScratchdisk, Path=FileList}">
...
</ItemsControl>

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

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.

在线28get { return (List&lt;string&gt;)GetValue(FileListProperty); }

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

有什么帮助吗?

谢谢!

【问题讨论】:

  • FileSystemWatcher 从不同的线程引发事件。尝试 changind Watcher_Created 做类似this.Dispatcher.Invoke(new Action(() =&gt; AddFileReference(e.FullPath))) 的事情。
  • @dkozl 这成功了,谢谢!

标签: c# wpf multithreading filesystemwatcher invalidoperationexception


【解决方案1】:

我访问它的方式是这样的。它获取 UI Thread 的 Dispatcher

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

在我所拥有的内容和您在 cmets 中列出的内容之间要注意的主要一点是,无论您是否在后面的代码、视图模型、服务类中,无论您在哪里,我的都可以工作。并非所有项目都有Dispatcher,因此this.Dispatcher 并不总是有效。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 如果您在视图模型中,这将不起作用。 'this' 可能没有调度程序。只有 UI 元素。因此,如果我尝试做 UI 工作,例如从后台线程更新绑定的 ObservableCollection,我将无法做到。
    • @AnthonyRussell 是的,这是真的。他没有说他是否使用了我认为他使用的代码中的对象。在这种情况下,它会起作用。
    【解决方案3】:

    尽管这是一个相当古老的线程,但我想给遇到与我相同的事情的任何人一个提示。这是一个故意冗长的描述,以便搜索引擎可以为下一个遇到这种晦涩行为的人/女孩找到它。

    在遇到 here 描述的 SetValue/GetValue 编译错误后,我需要从 DependencyObject 派生我的 VM。

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

    总有一个大毛“然而”。在测试过程中,发现我的一个组合框在选择一个项目时使整个应用程序崩溃。这是由于未处理的 InvalidOperationException。 “调用线程无法访问此对象,因为不同的线程拥有它。”使这个组合框与众不同的唯一原因是它使用 DependencyProperty 来处理某些值。

    四天令人沮丧的调试毫无结果,因为我的代码都没有进行调用。这一切都来自 WPF,当调用堆栈在GetValue 中到达VerifyAccess 时,它就爆炸了。显然,当它被框架调用时,尝试调用 Invoke 来跨线程不会发生?您会将 Invoke 调用放在哪里?

    由于正常调试失败,我只好硬着头皮去做。我回顾了我的签入步骤以找到代码最后一次工作的时间。我已经想到它与组合框的 DependencyProperty 有某种关联,所以看到代码更改,我的怀疑指向 DependencyObject 派生。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多