Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在DirectoryInfo.Enumerate文件完成之前访问它_C#_Winforms_Io_.net - Fatal编程技术网

C# 如何在DirectoryInfo.Enumerate文件完成之前访问它

C# 如何在DirectoryInfo.Enumerate文件完成之前访问它,c#,winforms,io,.net,C#,Winforms,Io,.net,在我问的问题和我发现的其他几个问题中,似乎搜索许多文件的方法是使用EnumerateFiles方法 EnumerateFiles和GetFiles方法的区别如下: 使用EnumerateFiles,可以开始枚举名称集合 在归还全部藏品之前;当您使用GetFiles时 必须等待返回整个名称数组,然后才能 访问阵列。因此,当您处理许多文件和 目录、枚举文件可以更高效 这对我来说听起来很棒,我的搜索大约需要10秒钟,所以我可以在收到信息时开始制作我的列表。但我想不出来。当我运行EnumerateFil

在我问的问题和我发现的其他几个问题中,似乎搜索许多文件的方法是使用EnumerateFiles方法

EnumerateFiles和GetFiles方法的区别如下: 使用EnumerateFiles,可以开始枚举名称集合 在归还全部藏品之前;当您使用GetFiles时 必须等待返回整个名称数组,然后才能 访问阵列。因此,当您处理许多文件和 目录、枚举文件可以更高效

这对我来说听起来很棒,我的搜索大约需要10秒钟,所以我可以在收到信息时开始制作我的列表。但我想不出来。当我运行EnumerateFiles方法时,应用程序将冻结直到完成。我可以在后台工作程序中运行它,但同样的事情也会发生在该线程上。有什么帮助吗

 DirectoryInfo dir = new DirectoryInfo(MainFolder);
 List<FileInfo> matches = new List<FileInfo>(dir.EnumerateFiles("*.docx",SearchOption.AllDirectories));

//This wont fire until after the entire collection is complete
DoSoemthingWhileWaiting();
DirectoryInfo dir=newdirectoryinfo(主文件夹);
列表匹配=新列表(dir.EnumerateFiles(“*.docx”,SearchOption.AllDirectories));
//直到整个收集完成后,才会触发
DoSoemthingWhileWaiting();
应用程序冻结,因为您正在通过将此可枚举项放入
列表的构造函数中来使用它。就好像你在急切地调用旧方法一样。因此,正确的方法是在后台线程中运行它,然后不要立即将结果传递给将一直使用可枚举项的对象,而是在它们到达循环时开始迭代并添加项

我可以在后台工作程序中运行它,但同样的事情也会发生在该线程上

是的,在循环期间,您显然会冻结后台线程,但这就是后台线程的目的:避免冻结主UI线程。只要确保在将项目传递到主线程以显示它们时,您正在使用与UI的正确同步。在WinForms中,这种情况发生在方法上。当然要小心,因为在后台线程和UI线程之间经常进行编组也会产生负面影响,让您感觉应用程序冻结了。要解决这个问题,您可以在文件成批到达时传递它们

下面是一个例子:

Task.Factory.StartNew(() =>
{
    var dir = new DirectoryInfo(MainFolder);
    var files = dir.EnumerateFiles("*.docx", SearchOption.AllDirectories);
    foreach (var file in files)
    {
        Action<string> del = f => listBox1.Items.Add((string)f);
        BeginInvoke(del, file);
    }
});
Task.Factory.StartNew(()=>
{
var dir=新目录信息(主文件夹);
var files=dir.EnumerateFiles(“*.docx”,SearchOption.AllDirectories);
foreach(文件中的var文件)
{
Action del=f=>listBox1.Items.Add((字符串)f);
BeginInvoke(del,文件);
}
});
您可以这样做

    forach(var f in dir.EnumerateFiles("*.docx",SearchOption.AllDirectories))
    {
//.. process file
    }

在线程中,并在进程完成后触发事件,您可以通过将其推入后台任务来完成此操作

例如,您可以执行以下操作:

var fileTask = Task.Factory.StartNew( () =>
{
    DirectoryInfo dir = new DirectoryInfo(MainFolder);
    return new List<FileInfo>(
           dir.EnumerateFiles("*.docx",SearchOption.AllDirectories)
           .Take(200) // In previous question, you mentioned only wanting 200 items
       );
};

// To process items:
fileTask.ContinueWith( t =>
{
     List<FileInfo> files = t.Result;

     // Use the results...
     foreach(var file in files)
     {
         this.listBox.Add(file); // Whatever you want here...
     }
}, TaskScheduler.FromCurrentSynchronizationContext()); // Make sure this runs on the UI thread

DoSomethingWhileWaiting();

所以,如果我立即运行这个,然后在5秒钟后再次运行,它们的结果可能会不同?我的意思是,在所有枚举完成之前,第一个文件会出现。如果您想处理文件系统更改,可以使用filesystemwatcher:哦,等等,我想我明白了。如果每次我运行这个程序,它都会找到一个结果,它将触发foreach的另一个迭代。。。在foreach中,我可以从后台工作程序向ui发送更新。。。是吗?是的,但别忘了与UIT同步Reed Copsey的第二个答案看起来很完美,所以如果我无法将其转换为列表,如何存储和访问它?很抱歉,我还没有得到这个结果?你想对这些结果做什么?在UI的某个地方显示它们?在列表框里还是什么?您不应该将它们存储在列表中。您应该将结果直接封送到主UI线程,以便在结果到达时显示。所以这实际上取决于你需要对结果做什么。是的,我想在列表中显示它们。当它们进入主界面时,将它们发送到主界面。我所缺少的是,如果后台工作人员在处理此操作时冻结,我如何将它们发送到主ui?使用Control.Invoke方法,分块发送。或者可以将它们存储在列表中,枚举完成后,可以使用Control.Invoke将此列表绑定到主UI控件。但在这种情况下,物品不会在到达时出现。感谢达林·弗雷奇在加巴的回答中,我想这促使我理解。谢谢你的帮助,谢谢你来晚了。我5分钟前就可以用这个了。这正是我想要的,但我已经从我过去的问题和上面的答案中找到了答案。非常感谢您抽出时间给出如此完整的答案。@K'Leg Faster!=更好;)我想我会告诉你可能需要的一切,包括不止一个选项……里德,看来我们在你的第二个答案中遗漏了一个结束括号。我尝试将其添加到末尾,但出现了错误。有什么想法吗?@K'Leg缺少一个括号-添加了它。应该是});在StartNewThanks的结尾,我才明白。我把它放在};)虽然它应该是在中间};
Task.Factory.StartNew( () =>
{
    DirectoryInfo dir = new DirectoryInfo(MainFolder);
    foreach(var tmp in dir.EnumerateFiles("*.docx",SearchOption.AllDirectories).Take(200))
    {
        string file = tmp; // Handle closure issue

        // You may want to do this in batches of >1 item...
        this.BeginInvoke( new Action(() =>
        {
             this.listBox.Add(file);
        }));
    }
});
DoSomethingWhileWaiting();