C# .Net 在遍历大量文件时冻结
C# .Net Freeze while iterating through large number of files
我有一个问题,我写了一个应用程序,它会遍历文件并对每个文件的整数加上 +1,直到它到达一个特定的文件名。问题可能是因为 .Net 不直接访问本机文件系统,它填满了集合,但在我的情况下,这将花费数年时间,相信我,目标文件夹中有 260 000 个文件。迭代甚至没有到达第二个文件。线程完全冻结,没有错误,没有异常。那么有什么方法可以直接访问本机文件系统而无需任何无用的集合填充?
这是我的代码:
private void button1_Click(object sender, EventArgs e)
{
try
{
foreach (string file in Directory.GetFiles("\\Mypcname-PC\vxheaven\malware"))
{
count++;
label1.Text = Convert.ToString(count);
if (file.Contains(textBox1.Text))
{
label1.Text = Convert.ToString(count) + " reached the file";
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
顺便说一句。抱歉我的英语不好
此致
因为您正在 UI 线程上完成所有工作,所以它在工作时无法刷新。您需要在后台线程上完成工作,然后以线程安全的方式更新 UI。另外切换到 Directory.EnumerateFiles
将使读取第一个文件的速度更快,因此它不需要将所有记录存储到数组中。最后,我将 ex.Message
更改为 ex.ToString()
,这样会显示更多有用的信息。
private async void button1_Click(object sender, EventArgs e)
{
try
{
var text = textBox1.Text;
var progress = new Progress<string>((x) => label1.Text = x);
await Task.Run(() => DoWork(progress, text));
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void DoWork(IProgress<string> progress, string text)
{
foreach (string file in Directory.EnumerateFiles("\\Mypcname-PC\vxheaven\malware"))
{
count++;
progress.Report(Convert.ToString(count));
if (file.Contains(text))
{
progress.Report(Convert.ToString(count) + " reached the file");
break;
}
}
}
(代码是凭记忆在网络浏览器中编写的,因此可能存在错误)
似乎您正在使用一个可能非常耗时的循环,而没有处理 Windows 消息队列,因此您的应用程序可能看起来被冻结了,而它可能只是忙于执行您指示它执行的操作在循环。试试这个:
private void button1_Click(object sender, EventArgs e)
{
try
{
foreach (string file in Directory.GetFiles("\\Mypcname-PC\vxheaven\malware"))
{
count++;
label1.Text = Convert.ToString(count);
Application.DoEvents();
if (file.Contains(textBox1.Text))
{
label1.Text = Convert.ToString(count) + " reached the file";
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
我有一个问题,我写了一个应用程序,它会遍历文件并对每个文件的整数加上 +1,直到它到达一个特定的文件名。问题可能是因为 .Net 不直接访问本机文件系统,它填满了集合,但在我的情况下,这将花费数年时间,相信我,目标文件夹中有 260 000 个文件。迭代甚至没有到达第二个文件。线程完全冻结,没有错误,没有异常。那么有什么方法可以直接访问本机文件系统而无需任何无用的集合填充?
这是我的代码:
private void button1_Click(object sender, EventArgs e)
{
try
{
foreach (string file in Directory.GetFiles("\\Mypcname-PC\vxheaven\malware"))
{
count++;
label1.Text = Convert.ToString(count);
if (file.Contains(textBox1.Text))
{
label1.Text = Convert.ToString(count) + " reached the file";
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
顺便说一句。抱歉我的英语不好
此致
因为您正在 UI 线程上完成所有工作,所以它在工作时无法刷新。您需要在后台线程上完成工作,然后以线程安全的方式更新 UI。另外切换到 Directory.EnumerateFiles
将使读取第一个文件的速度更快,因此它不需要将所有记录存储到数组中。最后,我将 ex.Message
更改为 ex.ToString()
,这样会显示更多有用的信息。
private async void button1_Click(object sender, EventArgs e)
{
try
{
var text = textBox1.Text;
var progress = new Progress<string>((x) => label1.Text = x);
await Task.Run(() => DoWork(progress, text));
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void DoWork(IProgress<string> progress, string text)
{
foreach (string file in Directory.EnumerateFiles("\\Mypcname-PC\vxheaven\malware"))
{
count++;
progress.Report(Convert.ToString(count));
if (file.Contains(text))
{
progress.Report(Convert.ToString(count) + " reached the file");
break;
}
}
}
(代码是凭记忆在网络浏览器中编写的,因此可能存在错误)
似乎您正在使用一个可能非常耗时的循环,而没有处理 Windows 消息队列,因此您的应用程序可能看起来被冻结了,而它可能只是忙于执行您指示它执行的操作在循环。试试这个:
private void button1_Click(object sender, EventArgs e)
{
try
{
foreach (string file in Directory.GetFiles("\\Mypcname-PC\vxheaven\malware"))
{
count++;
label1.Text = Convert.ToString(count);
Application.DoEvents();
if (file.Contains(textBox1.Text))
{
label1.Text = Convert.ToString(count) + " reached the file";
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}