当文本和进度条发生更改时,GUI会冻结

时间:2014-01-27 22:29:21

标签: c# winforms progress-bar backgroundworker

我正在创建一个使用TextBox和ProgressBar的程序,每次TextBox中的文本更改或ProgressBar执行一步时,GUI都会冻结,在操作完成之前我无法执行任何操作。

我知道我需要在不同的线程上运行它们,但是我搜索了整个网络,并没有找到适合我的方法。

这是我写文件的一个例子,我需要得到它的进展:

for (int l = 0; l < newfile.Length; l++)
{
  vfswriter.Write(newfile[l]);
  double percentage = ((double)l / (double)newfile.Length * 100);
  this.progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
}

这是我更改文字时的一个例子:

this.richTextBox1.Text = "Installing patch : ";

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:3)

使用BackgroundWorker,将您的for循环放在DoWork方法中:

backgroundWorker1.DoWork += doWork;

private void doWork(object sender, DoWorkEventArgs e)
{
    for (int l = 0; l < newfile.Length; l++)
    {
       vfswriter.Write(newfile[l]);
       double percentage = ((double)l / (double)newfile.Length * 100);
       this.progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
    }
}

如果要执行循环调用backgroundWorker1.RunWorkerAsync()方法。

您还可以使用ProgressChanged事件来更新进度条:

backgroundWorker1.DoWork += doWork;
backgroundWorker1.ProgressChanged += progressChanged;

private void doWork(object sender, DoWorkEventArgs e)
{
    for (int l = 0; l < newfile.Length; l++)
    {
       vfswriter.Write(newfile[l]);
       double percentage = ((double)l / (double)newfile.Length * 100);
       var value = int.Parse(Math.Truncate(percentage).ToString());
       backgroundWorker1.ReportProgress(value);
    }
}

private void progressChanged(object sender, ProgressChangedEventArgs e)
{
    this.progressBar1.Value = e.ProgressPercentage;
}

更新:如果您想将参数传递给DoWork方法,可以在调用backgroundWorker1.RunWorkerAsync()方法时执行此操作:

backgroundWorker1.RunWorkerAsync(argument);

您可以使用DoWorke.Argument方式访问它。如果你想传递多个参数,可以使用Anonymous Types来完成。例如:

var myArguments = new { Property1 = "some value", Property2 = myId, Property3 = myList };
backgroundWorker1.RunWorkerAsync(myArguments);

在DoWork方法中:

dynamic arguments = e.Argument;
var arg1 = arguments.Property1;
var arg2 = arguments.Property2;
// and so on...

答案 1 :(得分:0)

您可以使用Task类来创建和运行后台线程。一句谨慎!每当您想要从不是主线程的线程更新某些东西时,您必须使用Dispatcher在主线程上运行代码。

我的示例代码:

System.Threading.Tasks.Task task = new System.Threading.Tasks.Task(() =>
{
 for (int l = 0; l < newfile.Length; l++)
 {
   vfswriter.Write(newfile[l]);
   double percentage = ((double)l / (double)newfile.Length * 100);
   //This runs the code inside it on the main thread (required for any GUI actions
   App.Current.Dispatcher.Invoke((Action) (() =>
   {
     this.progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
   }
 }
});
task.Start();