Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

directory.GetFiles, how do i get it to spit out items as it finds them?

i'm using Directory.GetFiles to give me mp3 files, and i'd like to fill a ListBox with the results, but instead of stopping the program while it goes through the method, can i get it to search and fill the ListBox up as it gets the mp3 files?

so what i'm using is as follows (and it is failing to add them one at at time, it is adding them all at once when it is done)

private List<string> Getmp3sFromFolders(string folder)
    {
       List<string> fileArray = new List<string>();

       try
       {
           DirectoryInfo dir = new DirectoryInfo(folder);
           var files = dir.EnumerateFiles("*.mp3");
           foreach (var file in files)
           {

               fileArray.Add(file.FullName);
               Dispatcher.BeginInvoke(_AddMP3ToListbox, file.Name);
           }

           var directories = dir.EnumerateDirectories();
           foreach (var subdir in directories)
           {
               fileArray.AddRange(Getmp3sFromFolders(subdir.FullName));

           }

          // lblFolderSearching.Content = folder.ToString();
       }
       catch
       {

       }
       return fileArray;
    }

i did add _AddMP3ToListbox = AddMP3ToListbox

it does indeed add the mp3's to the listbox, but it does so all at once, not as soon as it finds it. how can i fix this?

like image 364
darthwillard Avatar asked May 19 '11 20:05

darthwillard


1 Answers

Use Directory.EnumerateFiles instead of Directory.GetFiles. EnumerateFiles will return the files as they're found by the system - not wait for all of them to be found.

Do this on a background thread and use Dispatcher.Invoke or Dispatcher.BeginInvoke to the UI thread as each one is found to add it to the ListBox.

Here's a quick example I threw together. Here's the XAML:

<Window x:Class="WpfApplication1.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">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <ListBox x:Name="_FileList" />
        <Button Grid.Row="1" Content="Go!" Click="Button_Click" />
    </Grid>
</Window>

and here's the code-behind:

using System;
using System.IO;
using System.Windows;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Action<string> _AddToListBox;

        public MainWindow()
        {
            InitializeComponent();
            _AddToListBox = AddToListBox;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Action action = Go;
            action.BeginInvoke(null, null);
        }

        private void Go()
        {
            foreach (var file in Directory.EnumerateFiles(@"c:\windows\system32\"))
            {
                Dispatcher.BeginInvoke(_AddToListBox, file);
            }
        }

        private void AddToListBox(string toAdd)
        {
            _FileList.Items.Add(toAdd);
        }
    }
}

by no means do I intend for this to be a best-practices or all-encompassing example. Just showing you one way to do it. By the way, I picked the system32 directory just because it has a lot of files in it so I could test it. Still works almost instantly on my machine though.

like image 99
Tim Avatar answered Oct 14 '22 23:10

Tim