2012-05-16 68 views
2

我想從FileSystemWatcher事件更新ListBox。當事件運行時,我得到這個錯誤:從FileSystemWatcher事件更新列表框

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); 
     } 
    } 
} 

任何建議如何做到這一點?

回答

5

這裏的問題是,FileSystemWatcher引發線程池上的事件而不是UI線程,但UI只能從UI線程修改。您修改它來處理這個

一種方法之前,您需要將事件處理代碼回到UI線程與SynchronizationContext

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

在我的系統,'POST'需要兩個參數,一個也沒有。一旦我改變了調用:'context.Post((val)=> listBox.Items.Add(e.FullPath),true);'它工作。謝謝Jared! – dharmatech

+0

看起來你更新了對'Post'的調用,但它仍然只接收一個參數。 :-) – dharmatech

+0

@dharmatech好抓,忘了國家的說法 – JaredPar