从另一个线程和类更新C#GUI中的进度条

时间:2012-05-23 21:33:04

标签: c# multithreading progress-bar

  

可能重复:
  Updating a Progress Bar from Another Thread

在我的程序中,我想将非GUI函数分离到另一个类,并在主类中保留与GUI相关的内容。但是,当工作者类中的一个工作方法正在执行其工作时,我遇到了更新进度条的问题。我知道我将不得不在这里使用多线程,但我不明白如何。我可能只是缺少简单的东西,但是当我查找有关它的信息时,似乎大多数教程都会讨论细节,但不能很好地解释大局。我部分理解调用和委托命令是什么,但我真的不明白它们是如何交互的。

下面是我要做的事情的精简版。如何修改此更新以更新进度条,但保持窗口响应并重新绘制?

主要表格类:

public partial class Form1 : Form
{
    time_waster thing = new time_waster();

    public Form1()
    {
        InitializeComponent();
        progressBar1.Minimum = 0;
        progressBar1.Maximum = 100;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        thing.something_that_takes_a_while();
    }
}

单独的工人阶级:     class time_waster     {         public time_waster()         {         }

    public void something_that_takes_a_while()
    {
        int delay = 200;
        for (int i = 0; i < 100; i++)
        {
            Thread.Sleep(delay);
            //appropriate code to update the progress bar for each iteration of the for loop.
        }
    }
}

3 个答案:

答案 0 :(得分:6)

.NET包含一个名为BackgroundWorker的类,它提供了报告事件中后台线程进度的方法。在创建BackgroundWorker的线程(通常是UI线程)上自动调用该事件。

订阅“ProgressChanged”事件,并更新该事件处理程序中的进度条。官方MSDN文档提供了一些示例代码。

答案 1 :(得分:4)

MethodInvoker mi = new MethodInvoker(() => progressBar.Progress = newProgressValue);
if (progressBar.InvokeRequired)
{
    progressBar.Invoke(mi);
}
else
{
    mi.Invoke();
}

此代码属于冗长的任务。参见:

  1. InvokeRequired
  2. Invoke
  3. Delegates
  4. 对于在内联声明而不是作为类上的方法或作为支持它们的语言中的原始函数的函数(或方法),Lambda只是一个过于乐观的词。如果不将其分配给命名变量,则它是“匿名的”。要小心,因为它们“捕获”它们所需的变量,如果你不理解它们,它们可能会有点奇怪。

    lambdas的语法非常简单:() => someValue;public void SomeMethod() { return someValue; }几乎相同,将括号放入括号中以向lambda添加参数。如果您只有一个参数,请随意跳过括号。

答案 2 :(得分:1)

   static main()
    {
         Thread th = new Thread(calling_function);
         th.start();  
    }


    calling_function()
    {
        //do your work;
        MethodInvoker m = new MethodInvoker( ()=> progressbar.Progress=value);
        progressbar.Invoke(m);
    }