Reputation: 81
I would appreciate your advice on my problem below:
I need my desktop WPF app to run two separate threads:
First thread: scanning the directory for files.
Second thread: receives FileInfo object from the first thread and puts it as new TreeViewItem in treeview control.
I am trying to solve this using Monitor
static methods.
public partial class MainWindow : Window
{
private Thread scanThread, treeThread;
public FileInfo scannedFile;
public object _lock = new object();
public MainWindow()
{
InitializeComponent();
scanThread = new Thread(new ParameterizedThreadStart(Scan));
treeThread = new Thread(new ThreadStart(PopulateTree));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
DirectoryInfo directory = new DirectoryInfo(FolderPath.Text); //I get FolderPath from FolderBrowserDialog
scanThread.Start(directory);
treeThread.Start();
}
public void Scan(object dir)
{
DirectoryInfo _directory = (DirectoryInfo)dir;
foreach (var file in _directory.GetFiles())
{
lock (_lock)
{
scannedFile = file;
Monitor.Pulse(_lock);
Monitor.Wait(_lock);
}
}
}
public void PopulateTree()
{
this.Dispatcher.Invoke(() =>
{
if (scannedFile== null)
return;
lock (_lock)
{
var dirNode = new TreeViewItem();
dirNode.Items.Add(scannedFile.Name);
dirNode.Header = scannedFile.Name;
MyTreeView.Items.Add(dirNode);
Monitor.Pulse(_lock);
Monitor.Wait(_lock);
}
});
}
Eventually I get random strange results - either no treeview population at all or only last file from folder is added to treeview.
Maybe it's the Monitor
logic I can't get to work properly, or I should not use public scannedFile variable and pass each var file in _directory.GetFiles()
in another way to second thread? Thank you in advance!
Update
I am limited to some basic techniques like Monitor/waithandle so the solution must be made in bounds of these techniques
Upvotes: 0
Views: 487
Reputation: 21641
I'd recommend adopting a MVVM pattern if you're using WPF. You should avoid using code behinds in the window and instead let WPF take care of the monitoring/threading logic. To do that, you should create a Model of your file/directory objects (maybe with a parent class of FileSystemObject
or something like that). You would then in your ViewModel have some kind of ObservableCollection<FileSystemObject>
available for rendering in your View, which would contain your TreeView
. WPF TreeView ObservableCollection notifying sample code has a good example of doing something similar to that which you could use as a starting point.
Upvotes: 3