C# 有没有办法停止Directory.GetFiles搜索

C# 有没有办法停止Directory.GetFiles搜索,c#,directory,getfiles,C#,Directory,Getfiles,我正在使用Directory.GetFiles()搜索多文件夹目录中的文件,其中一些文件夹太大,搜索可能需要60秒。在下面的代码中,在用户停止键入之后,搜索开始第二次,当用户键入文件名并且在键入文件时不停顿时,这很有效,但是如果他/她在单词中间停顿,搜索将开始,并且即使他/她重新键入,也不会停止,直到结束。 我想做的是在用户键入时停止搜索,可能是在inputFileName\u TextChanged方法中 使用Directory.GetFiles时,是否有方法停止已启动的搜索 using Sy

我正在使用
Directory.GetFiles()
搜索多文件夹目录中的文件,其中一些文件夹太大,搜索可能需要60秒。在下面的代码中,在用户停止键入之后,搜索开始第二次,当用户键入文件名并且在键入文件时不停顿时,这很有效,但是如果他/她在单词中间停顿,搜索将开始,并且即使他/她重新键入,也不会停止,直到结束。 我想做的是在用户键入时停止搜索,可能是在inputFileName\u TextChanged方法中

使用
Directory.GetFiles
时,是否有方法停止已启动的搜索

using System.Timers;
using System.IO;

namespace findFileTest
{

    public partial class MainWindow : Window
    {
        Timer timer = new Timer();

        public MainWindow()
        {
            InitializeComponent();

            timer.Elapsed += new ElapsedEventHandler(TimerEvent);
            timer.Interval = 1000;
            timer.Enabled = true;
            timer.Stop();
        }

        private void inputFileName_TextChanged(object sender, TextChangedEventArgs e)
        {
            // How to stop the search currently in process here
            timer.Stop();
            timer.Start();
        }

        public void TimerEvent(object source, ElapsedEventArgs e)
        {
            timer.Stop();
            findFile();
        }

        private void findFile()
        {
            string fName = "";

            this.Dispatcher.Invoke(() => {
                fName = inputFileName.Text;
            });

            var fType = ".txt";
            var fileName = fName.Trim() + fType;

            var file = Directory.GetFiles(@"C:\TestFolder\", fileName, SearchOption.AllDirectories).FirstOrDefault();
            if (file == null) {
                Console.WriteLine("File not found");
            }
            else {
                Console.WriteLine("Found:" + file);
            }
        }
    }
}
使用Directory.GetFiles时,是否有方法停止已启动的搜索

不,不安全。
GetFiles()
方法在返回之前不提供任何中断其工作的机制。您必须中止线程,这将导致许多其他问题

如中所述,从字面上理解您的请求,答案是使用
Directory.EnumerateFiles()
方法。此方法通过提供一个一次返回一个文件的枚举器,呈现底层
FindFirstFile()
FindNextFile()
的语义。每次返回新文件时,您都有机会中断枚举并返回,而无需做更多工作

请注意,即使使用
EnumerateFiles()
,您也不会得到第一个文件结果,除非它找到与您的搜索模式匹配的内容。如果您切换到使用
EnumerateFiles()
,您可能还希望自己对输入进行匹配,而不是让
EnumerateFiles()
进行匹配。即,将
“*”
作为搜索字符串传递。这将使整个操作的速度降低一点,但您将有机会中断搜索目录和子目录中每个文件的操作,而不是仅在找到匹配的文件时

最后,我建议,考虑到您明显的用例,您可能需要重新考虑使用
目录
类。根据您发布的代码,每次用户输入一些新文本时,您都会启动对文件系统的搜索,这必然是一个缓慢的操作。依我看,最好只构建一次索引(例如,一个
字典
,它将不带扩展名的文件名映射到目录中每个匹配文件的完整路径,即
Path.GetFileNameWithoutExtension()
)。这样,你就不必打断任何事情。用户输入文本后的“搜索”部分几乎是即时的

当然,在目录被完全索引之前会有一个初始延迟。这取决于你如何处理。但我建议提供一种机制,既可以向用户指出索引尚未完全完成,也可以检查您拥有的内容,以防用户查找的文件与已索引的文件匹配

请注意,通常使用的Windows文件系统(FAT、FAT32、NTFS等)不区分大小写,因此您需要使用
StringComparer.OrdinalIgnoreCase
初始化字典。“序号”,因为文件系统名称需要与用户键入的确切字符匹配,并且“忽略大小写”,因此搜索不区分大小写


我猜在您的场景中,当用户使用您的程序搜索文件时,不太可能添加或删除文件。但是,如果您担心这种情况,您可以只向用户提供一个“刷新”按钮来强制重新索引目录,或者使用
FileSystemWatcher
在添加或删除文件时自动更新索引。

错误的方法,directory.EnumerateFiles()很容易停止。只需将从foreach循环中分离出来。@Peter Duniho在你的前两段中,你回答了我的一个问题:为什么要使用
目录.EnumerateFiles()
而不是
目录.GetFile()
,谢谢。建立索引的想法听起来很好,但听起来有点复杂,但我肯定会研究它。快速问题,索引文件通常是如何处理的,您会得到字典列表,然后保存它以便以后可以引用它?是的。
列表
是给定名称的所有文件名的完整路径列表。例如,如果您有三个目录,每个目录都有一个名为“foo.txt”的文件,那么您的词典在“foo”键下会有一个包含这三个文件的完整路径的列表。构建索引时,需要使用
TryGetValue()
查看键是否已经存在;如果是,您只需将找到的新文件添加到该键的列表中,如果不是,则首先创建列表,将其添加为该键的值,然后将新文件添加到新列表中。开始有意义了,没有扩展名的文件名将是键,路径将是
列表中的值。现在,由于完成第一个索引后,大多数请求将通过
列表而不是通过搜索来完成,因此
列表的大小是否有限制?谢谢。“大多数请求将通过列表完成”——如果你正在构建和使用索引,所有搜索都应该通过索引。“列表的大小有限制吗?”--所有的计算机都是有限的机器,所以是的……有限制。但是
List
类使用数组作为其底层存储,而.NET数组的大小可以是2GB。所以,虽然有一个限制,但这个限制远远大于你可能需要的。如果您确实以某种方式超过了该限制,那么您只需要一个更复杂的数据结构(例如,字典值列表)。