C# C代码需要很长时间才能运行。有没有办法让它更快完成?
我需要一些帮助。如果您在我的代码中输入一个目录,它将进入该目录中的每个文件夹并获取每个文件。通过这种方式,我通过使用代码绕过了“AccessDeniedException”,但是如果目录是一个包含大量数据和文件夹(例如:C:/)的目录,则需要花费大量的时间 我真的不知道如何使用多线程,在互联网上也找不到任何帮助。有没有办法通过多线程使代码运行得更快?或者可以要求代码使用更多内存或内核吗?我真的不知道,我需要你的建议 在每个子目录的每个文件中输入的代码:C# C代码需要很长时间才能运行。有没有办法让它更快完成?,c#,multithreading,recursion,subdirectory,C#,Multithreading,Recursion,Subdirectory,我需要一些帮助。如果您在我的代码中输入一个目录,它将进入该目录中的每个文件夹并获取每个文件。通过这种方式,我通过使用代码绕过了“AccessDeniedException”,但是如果目录是一个包含大量数据和文件夹(例如:C:/)的目录,则需要花费大量的时间 我真的不知道如何使用多线程,在互联网上也找不到任何帮助。有没有办法通过多线程使代码运行得更快?或者可以要求代码使用更多内存或内核吗?我真的不知道,我需要你的建议 在每个子目录的每个文件中输入的代码: public static List<
public static List<string> Files = new List<string>();
public static List<string> Exceptions = new List<string>();
public MainWindow()
{
InitializeComponent();
}
private static void GetFilesRecursively(string Directory)
{
try
{
foreach (string A in Directory.GetDirectories(Directory))
GetFilesRecursively(A);
foreach (string B in Directory.GetFiles(Directory))
AddtoList(B);
} catch (System.Exception ex) { Exceptions.Add(ex.ToString()); }
}
private static void AddtoList(string Result)
{
Files.Add(Result);
}
private void Btn_Click(object sender, RoutedEventArgs e)
{
GetFilesRecursively(Textbox1.Text);
foreach(string C in Files)
Textbox2.Text += $"{C} \n";
}
公共静态列表文件=新列表();
公共静态列表异常=新列表();
公共主窗口()
{
初始化组件();
}
私有静态void getfiles递归(字符串目录)
{
尝试
{
foreach(Directory.GetDirectories(Directory))中的字符串A)
递归地获取文件(A);
foreach(Directory.GetFiles(Directory)中的字符串B)
AddtoList(B);
}catch(System.Exception ex){Exceptions.Add(ex.ToString());}
}
私有静态void AddtoList(字符串结果)
{
文件。添加(结果);
}
私有无效Btn_单击(对象发送方,路由目标)
{
递归地获取文件(Textbox1.Text);
foreach(文件中的字符串C)
Textbox2.Text+=$“{C}\n”;
}
您不需要递归来避免无法访问的文件。您可以使用接受参数并设置为true
的重载:
var options=new EnumerationOptions
{
IgnoreInaccessible=true,
RecurseSubdirectories=true
};
var files=Directory.EnumerateFiles(somePath,"*",options);
附加文件路径的循环也非常昂贵。它不仅在每次迭代中创建一个新的临时字符串,还强制用户界面重画。通过创建单个字符串(例如使用string.Join
或StringBuilder
),可以提高速度和内存使用率(由于垃圾收集也会影响性能):
var text=String.Join("\n",files);
Textbox2.Text=text;
String.Join
在内部使用StringBuilder,其内部缓冲区在每次满时都会重新分配。必须对上一个缓冲区进行垃圾收集。Once甚至可以通过使用具有特定容量的StringBuilder
来避免这种情况。即使是粗略估计也可以显著减少再分配:
var builder=new StringBuilder(4096);
foreach(var file in files)
{
builder.AppendLine(file);
}
TaskSource
属性添加到类中,并wait
仅当深度超出限制时生成的Task
,并触发事件,以便您的UI可以挂接到操作并询问用户public class FileLocator
{
public FileLocator(int maxDeep = 6){
_maxDeep = maxDeep;
this.TaskSource = new TaskSource();
this.ConfirmTask = this.TaskSource.Task;
}
private int _maxDeep;
private int _deep;
public event Action<FileLocator> OnReachMaxDeep;
public Task ConfirmTask ;
public TaskSource TaskSource {get;}
public Task<List<string>> GetFilesRecursivelyAsync()
{
var result = new List<string>();
foreach(xxxxxxx)
{
xxxxxxxxxxxxxx;
this._deep +=1;
if(_deep == _maxDeep)
{ OnRichMaxDeep?.Invoke(this); }
if(_deep >= _maxDeep)
{
try{
await ConfirmTask;
continue;
}
catch{
return result;
}
}
}
}
}
扫描你的整个硬盘需要时间,不管你怎么做。即使是WinDirStat这样的应用程序也需要很长的时间才能完成。异常包含多少项?让异常发生是最后的手段,特别是当您谈论性能时。相反,您必须防止异常,例如在尝试访问文件夹之前检查文件夹权限。您的代码的用途是什么?要从您有权访问的目录及其子目录中获取文件列表,或者如果您也获得了异常,这是否重要?通过将搜索选项AllDirectories传递到GetFiles调用中,您可以调用目录上的GetFiles并包括子目录。在开始之前,您真的需要完整文件夹的结果吗?例如,如果我想到一个可视化的树,它就足以加载扩展的节点(按需)。@AsPas:在大多数情况下,读取文件系统时CPU不是你的问题。而文件系统往往会变得更慢,因为并行访问的进程越多。
var locator = new FileLocator();
locator.OnReachMaxDeep += (x)=> { var result = UI.Confirm(); if(result){ x.TaskSource.SetResult(); else{ x.TaskSource.SetException(new Exception()) } } }
var result = await locator.GetFilesRecursivelyAsync("C:");