Madcode
Madcode

Reputation: 81

Populate WPF treeview in separate thread

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

Answers (1)

Dan Field
Dan Field

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

Related Questions