0

I have a problem that I wrote an application that would iterate through files and add +1 to the integer each file, until it reaches a specific file name. The problem is probably because .Net does not access the native file system directly, it fills up collections, but in my case it would take years, believe me, I have 260 000 files in the target folder. The iteration does not even reach the second file. The thread just totally freezes, no errors, no exceptions. So is there any way to get a direct access to the Native File System without any useless collection filling ups?

Here is my code:

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);
    }
}

btw. Sorry for my bad english

Regards

Raktim Biswas
  • 4,011
  • 5
  • 27
  • 32
Yogibear
  • 153
  • 12

2 Answers2

10

Because you are doing all the work on the UI thread it can't refresh while it is working. You need to do the work on a background thread then update the UI in a thread safe way. Also switching to Directory.EnumerateFiles will make it faster to read the first file so it does not need to store all the records in to an array. Lastly I changed ex.Message to ex.ToString(), it will display much more useful information that way.

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;
        }
    }
}

(Code was written in a web browser from memory so there may be errors)

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
-1

Seems like you are using a potentially very time-consuming loop without ever processing the Windows message queue, therefore your application may APPEAR to be frozen, while it's probably just busy doing what you instructed it to do in the loop. Try this:

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);
    }
}
FjodrSo
  • 301
  • 2
  • 8
  • 1
    `Application.DoEvents();` is very dangerous to do, you can screw up the internal state of your program if you are not careful. You should not use it as your first choice of options. – Scott Chamberlain Jun 28 '16 at 18:43
  • That was a quick and dirty fix without changing his original code. Of course your code is a lot better (voting up your answer) but it's a complete rewrite, not a fix. ;) – FjodrSo Jun 28 '16 at 18:48