I’d like to update a ListBox from a FileSystemWatcher event. When the event runs, I’m getting this error:
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)
Here’s the code that demos the problem:
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);
}
}
}
Any suggestions on how to do this?
The problem here is that the
FileSystemWatcherraises it’s events on the thread pool and not the UI thread but the UI can only be modified from the UI thread. You need to move the event handling code back to the UI thread before you modify itOne way to handle this is with the
SynchronizationContext