I am using FileSystemWatcher to watch file creation in a folder, when any xml file is added /created in that folder, its file path will be displayed in a TextBox.
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
FileSystemWatcher w = new FileSystemWatcher();
public MainWindow()
{
InitializeComponent();
}
private void _startButton_Click(object sender, RoutedEventArgs e)
{
w.Path = @"D:\Temp";
w.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
// Only watch text files.
w.Filter = "*.xml";
// Add event handlers.
w.Created += new FileSystemEventHandler(OnChanged);
w.EnableRaisingEvents = true;
}
// Define the event handlers.
private void OnChanged(object source, FileSystemEventArgs e)
{
try
{
this.textBox1.Text = e.FullPath;
}
catch (Exception ex)
{
//
}
}
private void _stopButton_Click(object sender, RoutedEventArgs e)
{
w.EnableRaisingEvents = false;
}
}
}
when I run the program and add a xml file to the watched folder, a InvalidOperationException exception is thrown with the following messag:
"The calling thread cannot access this object because a different thread owns it."
Solution
By default FileSystemWatcher calls its registered event handlers in arbitrary threads. WPF/Forms doesnt allow this because method and properties on WPF/Forms UI objects should only be called on the thread that the WPF/Forms UI object was created.
To fix the issue, use txtBox1.Dispatcher.BeginInvoke(priority, uiMethod, args) to get you UI code sent to the UI thread to be executed:
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
FileSystemWatcher w = new FileSystemWatcher();
public MainWindow()
{
InitializeComponent();
}
private void _startButton_Click(object sender, RoutedEventArgs e)
{
w.Path = @"D:\Temp";
w.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
// Only watch text files.
w.Filter = "*.xml";
// Add event handlers.
w.Created += new FileSystemEventHandler(OnChanged);
w.EnableRaisingEvents = true;
}
private void AddMessage(string msg)
{
this.textBox1.Text += msg + Environment.NewLine;
}
private delegate void AddMessageDelegate(string msg);
// Define the event handlers.
private void OnChanged(object source, FileSystemEventArgs e)
{
AddMessageDelegate addMessage = new AddMessageDelegate(AddMessage);
this.textBox1.Dispatcher.BeginInvoke(addMessage, new object[] { e.FullPath });
}
private void _stopButton_Click(object sender, RoutedEventArgs e)
{
w.EnableRaisingEvents = false;
}
}
}