Winforms:避免冻结应用程序

时间:2009-11-15 09:33:50

标签: c# winforms performance

我在“大”文件(大约4Mb)上做了一些操作

我这样做: 1.从目录中获取所有文件并将它们放在IList中MyInfoClass具有以下属性:name,extension,fullPath,creationDate,contentPart 2.我做一个Linq查询只获得一些扩展类型。 3.我循环查询Linq查询结果,每次打开文件,执行一些操作(获取值)并将结果放入MyFileIno.ContentPart。

仅供参考:30个文件,这是14秒的操作

这是工作。

问题是,当我从UI运行我的库时,当我单击按钮时,窗口在操作期间冻结。我想:

  1. 不冻结表单的解决方案
  2. 查看进度操作
  3. 你能给我解决这类问题的最佳做法吗?

    谢谢,

    代码

    public class FileManager 
    {
        public string CurrentFileName { get; set; }
        public void Validation(string path)
        {
            IList<InfoFile> listFile = GetListFile(path);
            foreach (InfoFile item in listFile)
            {
                CurrentFileName = item.Name;
                .....
            }
        }
    }
    
    
    private void button1_Click(object sender, EventArgs e)
    {
        var worker = new BackgroundWorker();
        worker.DoWork += (s, args) =>
        {
            int percentProgress = 6;
            FileManager fileManager = new FileManager();
            fileManager.Validation(@"C:.....");
            ((BackgroundWorker)s).ReportProgress(percentProgress, fileManager.CurrentFileName);
        };
    
        worker.ProgressChanged += (s, args) =>
        {
            var currentFilename = (string)args.UserState;
            label1.Text = currentFilename;
            progressBar1.Value = args.ProgressPercentage;
        };
    
        worker.RunWorkerCompleted += (s, args) =>
        {
            progressBar1.Value = 0;
        };
        worker.RunWorkerAsync();
    }
    

1 个答案:

答案 0 :(得分:17)

应用程序冻结,因为您正在主线程中执行文件解析。您可以使用BackgroundWorker在新线程上执行操作。这里有一些伪代码可以帮助您入门:

private void button1_Click(object sender, EventArgs e)
{
    var worker = new BackgroundWorker();
    worker.DoWork += (s, args) =>
    {
        // Here you perform the operation and report progress:
        int percentProgress = ...
        string currentFilename = ...
        ((BackgroundWorker)s).ReportProgress(percentProgress, currentFilename);
        // Remark: Don't modify the GUI here because this runs on a different thread
    };
    worker.ProgressChanged += (s, args) =>
    {
        var currentFilename = (string)args.UserState;
        // TODO: show the current filename somewhere on the UI and update progress
        progressBar1.Value = args.ProgressPercentage;
    };
    worker.RunWorkerCompleted += (s, args) =>
    {
        // Remark: This runs when the DoWork method completes or throws an exception
        // If args.Error != null report to user that something went wrong
        progressBar1.Value = 0;
    };
    worker.RunWorkerAsync();
}