c# - 从 FileSystemWatcher 事件更新列表框

标签 c# wpf xaml

我想从 FileSystemWatcher 事件更新 ListBox。当事件运行时,我收到此错误:

Unhandled Exception: System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.
   at System.Windows.Threading.Dispatcher.VerifyAccess()
   at System.Windows.DependencyObject.GetValue(DependencyProperty dp)
   at System.Windows.Controls.Panel.get_IsItemsHost()
   at System.Windows.Controls.Panel.VerifyBoundState()
   at System.Windows.Controls.Panel.OnItemsChanged(Object sender, ItemsChangedEventArgs args)
   at System.Windows.Controls.ItemContainerGenerator.OnItemAdded(Object item, Int32 index)
   at System.Windows.Controls.ItemContainerGenerator.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   at System.Windows.Controls.ItemContainerGenerator.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, Eve
ntArgs e)
   at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list)
   at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args)
   at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)

   at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Windows.Controls.ItemCollection.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, EventArgs e
)
   at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list)
   at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args)
   at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)

   at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
   at MS.Internal.Controls.InnerItemCollectionView.Add(Object item)
   at System.Windows.Controls.ItemCollection.Add(Object newItem)
   at DirectoryBinding.MainWindow.<.ctor>b__2(Object s, FileSystemEventArgs e) in C:\Users\dharmatech\Documents\DirectoryBinding\DirectoryBi
nding\MainWindow.xaml.cs:line 35
   at System.IO.FileSystemWatcher.OnCreated(FileSystemEventArgs e)
   at System.IO.FileSystemWatcher.NotifyFileSystemEventArgs(Int32 action, String name)
   at System.IO.FileSystemWatcher.CompletionStatusChanged(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* overlappedPointer)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

这是演示该问题的代码:

Xaml:

<Window x:Class="DirectoryBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Height="350"
        Width="525">
    <DockPanel>
        <ListBox DockPanel.Dock="Top" Name="listBox"/>
    </DockPanel>
</Window>

C#

using System.Linq;
using System.Windows;
using System.IO;

namespace DirectoryBinding
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            new DirectoryInfo("c:/users/dharmatech").GetFileSystemInfos().ToList().ForEach(
                info => listBox.Items.Add(info.FullName));

            var fileSystemWatcher = new FileSystemWatcher("c:/users/dharmatech") 
            { EnableRaisingEvents = true };

            fileSystemWatcher.Created += (s, e) => listBox.Items.Add(e.FullPath);
        }
    }
}

关于如何做到这一点有什么建议吗?

最佳答案

这里的问题是,FileSystemWatcher 在线程池上引发事件,而不是 UI 线程,但 UI 只能从 UI 线程修改。修改之前需要将事件处理代码移回UI线程

处理此问题的一种方法是使用 SynchronizationContext

var context = SynchronizationContext.Current;
fileSystemWatcher.Created += (s, e) => {
  context.Post(val => listBox.Items.Add(e.FullPath), s);
};

关于c# - 从 FileSystemWatcher 事件更新列表框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10623513/

相关文章:

c# - SVCUTIL.EXE:有什么方法可以分离我的 Commons.xsd 类? (C#)

c# - 自动映射器 : Max graph depth

.net - 在单独的程序集中具有资源字典的智能感知

c# - 在 Window 的代码后面实现 IValueConverter

c# - 改进我选择具有唯一值的多个 XElement 以构建列表的方式

c# - 如何以编程方式触发命令

c# - WPF "Calendar only month"在悬停时触发 DisplayDateChanged

c# - 带有 SharedSizeGroup 列的网格表现得很奇怪(*不是*无限循环)

.net - 在 WPF MVVM 中绑定(bind)到没有代理对象的派生属性

c# - Defines.Debug 与 #if DEBUG