c# - 如何提高这个 "file explorer"启动速度?

标签 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 分钟才能开始......这真的很糟糕......希望你们能帮忙有更好的解决方案或算法?那简直太好了。提前致谢!

最佳答案

加载所有目录和文件是昂贵的 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 方法不是必需的。休息都一样。请随时提出任何说明。

希望这对您有所帮助。

关于c# - 如何提高这个 "file explorer"启动速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19059870/

相关文章:

c# - 哪些算法用于搜索单词中的子词?

c# - 如何根据displayindex获取listview的列标题列表?

android - 在 Android 中为 ArrayList 设置自定义适配器

c# - 找不到 WebClient

c# - 从封闭流中读取

string - 查找给定字符串中缺失的数字

Android - listView 中的自定义 CheckedTextView 在点击时未被选中/禁用 SINGLE_CHOICE 模式

c# - 抛出新的 ArgumentException

c# - HTML 页面抓取

algorithm - 梯度下降和爬山之间的行为差​​异