捆绑在一起,目录递归搜索+事件+线程

时间:2014-03-20 13:02:51

标签: c# multithreading recursion io

我想做的,并且致力于开发,是一个标准类,我可以用它来检索所有子目录(及其子目录和文件等)和文件。

WalkthroughDir(Dir)
  Files a
  Folders b
  WalkthroughDir(b[i])

简单的递归目录搜索。

以此为基础,我希望在以下情况下将其扩展为触发事件:

  • 找到了一个文件;
  • 找到目录;
  • 搜索完成

    private void GetDirectories(string path)
    {
        GetFiles(path);
    
        foreach (string dir in Directory.EnumerateDirectories(path))
        {
            if (DirectoryFound != null)
            {
                IOEventArgs<DirectoryInfo> args = new IOEventArgs<DirectoryInfo>(new DirectoryInfo(dir));
                DirectoryFound(this, args);
            }
    
            // do something with the directory...
    
            GetDirectories(dir, dirNode);
        }
    }
    
    private void GetFiles(string path)
    {
        foreach (string file in Directory.EnumerateFiles(path))
        {
            if (FileFound != null)
            {
                IOEventArgs<FileInfo> args = new IOEventArgs<FileInfo>(new FileInfo(file));
                FileFound(this, args);
            }
    
            // do something with the file...
        }
    }
    

如果您发现上述评论(&#34;做某事[...]&#34;),我可以将文件或目录添加到某些数据结构中。

执行此类搜索的最常见因素是处理时间,特别是对于大型目录。所以我很自然地希望这又向前迈出一步并实现线程化。现在,我对线程的了解非常有限,但到目前为止,这是我所提出的内容的概述:

    public void Search()
    {
        m_searchThread = new Thread(new ThreadStart(SearchThread));
        m_searching = true;
        m_searchThread.Start();
    }

    private void SearchThread()
    {
        GetDirectories(m_path);
        m_searching = false;
    }

如果我使用此实现,请在控件中分配事件,它会引发我的GUI应用程序尝试访问另一个线程的错误(正如我所料)。

任何人都可以就此实施提供反馈以及如何完成线程。感谢。

更新(selkathguy推荐):

这是按照selkathguy的建议调整后的代码:

    private void GetDirectories(DirectoryInfo path)
    {
        GetFiles(path);

        foreach (DirectoryInfo dir in path.GetDirectories())
        {
            if (DirectoryFound != null)
            {
                IOEventArgs<DirectoryInfo> args = new IOEventArgs<DirectoryInfo>(dir);
                DirectoryFound(this, args);
            }

            // do something with the directory...

            GetDirectories(dir);
        }
    }

    private void GetFiles(DirectoryInfo path)
    {
        foreach (FileInfo file in path.GetFiles())
        {
            if (FileFound != null)
            {
                IOEventArgs<FileInfo> args = new IOEventArgs<FileInfo>(file);
                FileFound(this, args);
            }

            // do something with the file...
        }
    }

原始编码时间:47.87秒

修改的代码时间:46.14s

1 个答案:

答案 0 :(得分:1)

要解决关于从标准类中引发自己的事件的请求的第一部分:您可以创建一个委托,其他方法可以作为事件的回调挂钩到该委托。请参阅http://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx作为一个很好的资源。实施起来相当简单。

至于线程,我认为至少对于您的性能问题是不必要的。递归检查目录的大多数性能瓶颈都在等待从磁盘加载节点信息。相对来说,这就是占用你所有时间的东西,因为获取目录信息是一个阻塞过程。使众多线程都检查不同的目录很容易降低搜索的整体速度,并且通过管理工作线程和委派工作份额极大地使应用程序复杂化。话虽如此,如果您的搜索跨越多个磁盘或资源位置,则可能需要每个磁盘都有一个线程。

我发现使用DirectoryInfo.GetDirectories()这样简单的递归是最快的解决方案之一,因为它利用了Windows已经实现的缓存。我用它做的搜索应用程序每秒可以搜索成千上万的文件名和目录名。