防止C#App冻结

时间:2013-12-04 11:55:46

标签: c#

我有一个C#应用程序,它读取文件夹中的所有文件,并将它们存储到一个数组中。然后应用程序将数组写入文本文件。

我想在标签中显示文件的名称。这是我尝试过的,但我的应用程序冻结,它只显示最后一个文件的名称。

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

4 个答案:

答案 0 :(得分:4)

您的应用程序正在冻结,因为您正在UI线程中完成所有工作。有许多替代品,比如使用线程,任务,后台工作者等等。

我将向您展示使用任务并行库的实现(假设您使用的是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++;
    }
}

如果您使用.net 4.5,则另一种方法是使用StreamWriter的WriteLineAsync

myWriter.WriteLineAsync(val);

答案 1 :(得分:2)

永远不要在UI线程中执行IO。 使用Stream上可用的*异步方法,或者旋转任务以异步写入文件。

答案 2 :(得分:0)

这是BackgroundWorker中理想的事情。它允许您通过ProgressChanged事件或Control.Invoke / Dispatcher.Invoke更新UI线程中的显示。

答案 3 :(得分:0)

BackgroundWorker类允许您在单独的专用线程上运行操作。下载和数据库事务等耗时的操作可能会导致用户界面(UI)在运行时停止响应。当您需要响应式UI并且您遇到与此类操作相关的长时间延迟时,BackgroundWorker类提供了一种方便的解决方案。

结帐Background Worker。 它包括代码示例。