c# - 如何提高这个“文件浏览器”的启动速度?

时间:2013-09-27 20:52:13

标签: c# algorithm listview treeview

我正在使用c#填充“文件资源管理器”解决方案。这是我的代码:

namespace NIXplorer
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

    TreeNode root = new TreeNode("Desktop");
    TreeNode doc = new TreeNode("My Documents");
    TreeNode comp = new TreeNode("My Computer ");
    TreeNode drivenode;
    TreeNode filenode;
    DirectoryInfo dir;
    string path = "";

    private void Form1_Load(object sender, EventArgs e)
    {
        listView1.LabelEdit = true;
        listView1.FullRowSelect = true;
        listView1.Sorting = SortOrder.Ascending;
        treeView1.Nodes.Add(root);
        root.ImageIndex = 0;
        doc.ImageIndex = 1;
        comp.ImageIndex = 2;
        treeView1.Nodes.Add(doc);
        treeView1.Nodes.Add(comp);
        GetDrives();
    }

    private void GetDrives()
    {
        DriveInfo[] drive = DriveInfo.GetDrives();
        foreach (DriveInfo d in drive)
        {
            drivenode = new TreeNode(d.Name);
            dir = d.RootDirectory;
            comp.Nodes.Add(drivenode);
            //drivenode.ImageIndex = 3;
            switch (d.DriveType)
            {
                case DriveType.CDRom:
                    drivenode.ImageIndex = 5;
                    break;
                //case DriveType.Fixed:
                //    drivenode.ImageIndex = 1;
                //    break;
                case DriveType.Removable:
                    drivenode.ImageIndex = 8;
                    break;
                //case DriveType.NoRootDirectory:

                //    drivenode.ImageIndex = 5;
                //    break;
                case DriveType.Network:
                    drivenode.ImageIndex = 6;
                    break;
                default:
                    drivenode.ImageIndex = 7;
                    break;
            }
            getFilesAndDir(drivenode, dir);
        }
    }

    private void getFilesAndDir(TreeNode node, DirectoryInfo dirname)
    {
        try
        {
            foreach (FileInfo fi in dirname.GetFiles())
            {
                filenode = new TreeNode(fi.Name);
                filenode.Name = fi.FullName;
                //filenode.ImageIndex = 5;
                getFileExtension(filenode.Name);
                node.Nodes.Add(filenode);
            }
            try
            {
                foreach (DirectoryInfo di in dirname.GetDirectories())
                {
                    TreeNode dirnode = new TreeNode(di.Name);
                    dirnode.ImageIndex = 4;
                    dirnode.Name = di.FullName;
                    node.Nodes.Add(dirnode);
                    getFilesAndDir(dirnode, di); //Recursive Functioning
                }
            }
            catch (Exception e1)
            {
            }
        }
        catch (Exception e1)
        {
        }
    }

    private void getFileExtension(string filename)
    {
        switch (Path.GetExtension(filename))
        {
            case ".txt":
                filenode.ImageIndex = 17;
                break;
            case ".rtf":
                filenode.ImageIndex = 16;
                break;
            case ".doc":
            case ".docx":
                filenode.ImageIndex = 9;
                break;
            case ".html":
            case ".htm":
                filenode.ImageIndex = 13;
                break;
            case ".rar":
            case ".zip":
                filenode.ImageIndex = 10;
                break;
            case ".exe":
                filenode.ImageIndex = 12;
                break;
            case ".mp3":
            case ".wma":
            case ".flac":
            case ".m4a":
                filenode.ImageIndex = 11;
                break;
            case ".mp4":
            case ".flv":
            case ".mkv":
            case ".webm":
                filenode.ImageIndex = 18;
                break;
            case ".ico":
            case ".png":
            case ".jpg":
            case ".jpeg":
            case ".psd":
                filenode.ImageIndex = 14;
                break;
            default:
                filenode.ImageIndex = 15;
                break;
        }
    }

    private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
    {
        try
        {
            listView1.Items.Clear();
            TreeNode selectednode = e.Node;
            treeView1.SelectedNode.ImageIndex = e.Node.ImageIndex;
            selectednode.Expand();
            comboBox1.Text = selectednode.FullPath;
            if (selectednode.Nodes.Count > 0)
            {
                foreach (TreeNode n in selectednode.Nodes)
                {
                    ListViewItem lst = new ListViewItem(n.Text, n.ImageIndex);
                    lst.Name = n.FullPath.Substring(13);
                    //MessageBox.Show("List Node : " + lst.Name);
                    listView1.Items.Add(lst);
                }
            }
            else
            {
                listView1.Items.Add(selectednode.FullPath, selectednode.Text, selectednode.ImageIndex);
            }
        }
        catch (Exception e1)
        {
        }
    }
}
}

我在VS2012中构建这个解决方案,这个算法似乎不是最好的选择'因为每次我调试这个解决方案,开始需要超过1或2分钟...这真的很糟糕...希望你们可以帮助有更好的解决方案或算法?那简直太好了。提前谢谢!

2 个答案:

答案 0 :(得分:1)

加载所有目录和文件是昂贵的IO操作。在没有必要时不要加载所有东西。用户不会一直查看所有内容。

我建议你按需填充。这样的事情。

    class FileSystemObject
    {
        public FileSystemInfo FileSystemInfo;
        public FileSystemObjectType ObjectType;
        public bool SubNodesLoaded;
    }

    enum FileSystemObjectType
    {
        File = 1,
        Directory = 2
    }

    private void GetDrives()
    {
        DriveInfo[] drive = DriveInfo.GetDrives();
        foreach (DriveInfo d in drive)
        {
            drivenode = new TreeNode(d.Name);
            dir = d.RootDirectory;
            drivenode.Tag = new FileSystemObject { FileSystemInfo = dir, ObjectType = FileSystemObjectType.Directory };
            comp.Nodes.Add(drivenode);
            //drivenode.ImageIndex = 3;
            switch (d.DriveType)
            {
                case DriveType.CDRom:
                    drivenode.ImageIndex = 5;
                    break;
                //case DriveType.Fixed:
                //    drivenode.ImageIndex = 1;
                //    break;
                case DriveType.Removable:
                    drivenode.ImageIndex = 8;
                    break;
                //case DriveType.NoRootDirectory:

                //    drivenode.ImageIndex = 5;
                //    break;
                case DriveType.Network:
                    drivenode.ImageIndex = 6;
                    break;
                default:
                    drivenode.ImageIndex = 7;
                    break;
            }

            EnsureChildsLoaded(drivenode);
        }
    }

    private void EnsureChildsLoaded(TreeNode node)
    {
        try
        {
            FileSystemObject info = (FileSystemObject)node.Tag;
            if (info == null || info.ObjectType == FileSystemObjectType.File || info.SubNodesLoaded)
            {
                return;
            }               

            DirectoryInfo dirInfo = (DirectoryInfo)info.FileSystemInfo;
            // while (!new DriveInfo(dirInfo.Root.FullName).IsReady)
            {
                dirInfo.Refresh();
            }

            foreach (FileInfo fi in dirInfo.GetFiles())
            {
                filenode = new TreeNode(fi.Name);
                filenode.Name = fi.FullName;
                //filenode.ImageIndex = 5;
                getFileExtension(filenode.Name);
                filenode.Tag = new FileSystemObject { FileSystemInfo = fi, ObjectType = FileSystemObjectType.File };
                node.Nodes.Add(filenode);

            }

            foreach (DirectoryInfo di in dirInfo.GetDirectories())
            {
                TreeNode dirnode = new TreeNode(di.Name);
                dirnode.ImageIndex = 4;
                dirnode.Name = di.FullName;
                dirnode.Tag = new FileSystemObject { FileSystemInfo = di, ObjectType = FileSystemObjectType.Directory };
                node.Nodes.Add(dirnode);
            }

            info.SubNodesLoaded = true;
        }
        catch (Exception ex){//log it }
    }

    private void treeView1_AfterExpand(object sender, TreeViewEventArgs e)
    {
        //Load two level of nodes on demand
        FileSystemObject info = (FileSystemObject)e.Node.Tag;
        EnsureChildsLoaded(e.Node);
        foreach (TreeNode node in e.Node.Nodes)
        {
            EnsureChildsLoaded(node);
        }
    }

不需要getFilesAndDir方法。一切都一样。随意提出任何澄清。

希望这有帮助。

答案 1 :(得分:0)

GetFiles本质上很慢,因为您必须等待返回整个数组,然后才能与它进行交互。 如果您改为使用Directory.EnumerateFiles,则可以在返回之前开始枚举集合(并填充树)。 http://msdn.microsoft.com/en-us/library/dd383458.aspx