2

I have a C# app that reads all the files in a folder, storing them into an array. Then the app writes the array to a text file.

I want to display the name of the file in a label. Here is what I have tried, but my app freezes and it displays only the name of the last file.

 private void button1_Click(object sender, EventArgs e)
    {
        ListAllFiles(@"C:\mmc2", ref label1);

    }


    private void ListAllFiles(string path, ref Label lbl)
    {
        string savePath = @"C:\Users\Diza\Desktop\AllFiles.txt";
        string[] files = Directory.GetFiles(path,"*.*", SearchOption.AllDirectories);
        StreamWriter myWriter = new StreamWriter(savePath);
        int count=0;
        DateTime dtStart = DateTime.Now;

        myWriter.WriteLine("Start: " + dtStart.ToShortTimeString());

        foreach (string val in files)
        {
            lbl.Text = val;
            myWriter.WriteLine(val);
            count++;
        }
    }
Alberto Solano
  • 7,972
  • 3
  • 38
  • 61
user3001242
  • 21
  • 1
  • 3
  • To prevent "freezing" in general you'll want to look into multi-threading. What's happening is all of your code, both the UI rendering and the file I/O, is happening in the same thread. So one can't do anything until the other one is completed. You always want to separate the UI thread from any background logic threads so that the UI can still update and handle user interactions. – David Dec 04 '13 at 12:02
  • check out [this](http://stackoverflow.com/a/14455437/847349) answer – Dmitry Ledentsov Dec 04 '13 at 12:07
  • I have figured that I can use a backgroundworker (never used one before though) and call my Function in the backgroundworker and Call the backgroundworker .RunWorkerAsync in the button – user3001242 Dec 04 '13 at 13:11

4 Answers4

4

Your application is freezing because you are doing all the work in the UI thread. There are a lot of alternatives like using a thread, a task, a background worker and so on.

I will show you an implementation using the task parallel library (and assuming you are using wpf):

private void button1_Click(object sender, EventArgs e)
{
    //Start the listing in a task
    Task.Factory.StartNew(()=>ListAllFiles(@"C:\mmc2", ref label1));
}


private void ListAllFiles(string path, ref Label lbl)
{
    string savePath = @"C:\Users\Diza\Desktop\AllFiles.txt";
    string[] files = Directory.GetFiles(path,"*.*", SearchOption.AllDirectories);
    StreamWriter myWriter = new StreamWriter(savePath);
    int count=0;
    DateTime dtStart = DateTime.Now;

    myWriter.WriteLine("Start: " + dtStart.ToShortTimeString());

    foreach (string val in files)
    {
        //update the label using the dispatcher (because ui elements cannot be accessed from an non-ui thread
        Application.Current.Dispatcher.BeginInvoke(
           new Action(()=>lbl.Text = val));

        myWriter.WriteLine(val);
        count++;
    }
}

Another alternative if you are using the .net 4.5 is using the WriteLineAsync of the StreamWriter:

myWriter.WriteLineAsync(val);
Alberto
  • 15,626
  • 9
  • 43
  • 56
2

Never do IO in the UI thread. Use *Async methods available on Stream or spin up a Task to write file asynchronously.

Alexey Raga
  • 7,457
  • 1
  • 31
  • 40
0

This is the ideal thing to do in a BackgroundWorker. It allows you to update the display in the UI thread through its ProgressChanged event or through Control.Invoke/Dispatcher.Invoke.

Thorsten Dittmar
  • 55,956
  • 8
  • 91
  • 139
0

The BackgroundWorker class allows you to run an operation on a separate, dedicated thread. Time-consuming operations like downloads and database transactions can cause your user interface (UI) to seem as though it has stopped responding while they are running. When you want a responsive UI and you are faced with long delays associated with such operations, the BackgroundWorker class provides a convenient solution.

Check out Background Worker. It include code examples.

mnemonic
  • 1,605
  • 2
  • 17
  • 26