user3001242
user3001242

Reputation: 21

Prevent C# App from freezing

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

Upvotes: 2

Views: 6528

Answers (4)

mnemonic
mnemonic

Reputation: 1645

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.

Upvotes: 0

Thorsten Dittmar
Thorsten Dittmar

Reputation: 56727

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.

Upvotes: 0

Alberto
Alberto

Reputation: 15951

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

Upvotes: 4

Alexey Raga
Alexey Raga

Reputation: 7545

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

Upvotes: 2

Related Questions