【问题标题】:adding a progress bar添加进度条
【发布时间】:2011-09-25 14:42:17
【问题描述】:

我有一个使用一个类的 Windows 窗体应用程序(它的名称是 Parser) 此表单有一个按钮,当我单击 Windows 表单应用程序按钮时,它会调用解析器类方法之一。

此方法只是逐行读取文本文件并将每一行写入单独的文件...

我想在表单中添加一个进度条以显示进度(这是一个非常大的文件)

知道怎么做吗?我在 Parse 类 2 属性中第一个是文件中的行数,第二个是已经检查了多少行。

这是我的button2_Click 函数

private void button2_Click(object sender, EventArgs e)
{
      if (this.textBox1 != null & this.textBox2 != null)
      {
           inst.init(this.textBox1.Text, this.textBox2.Text);
           //this.progressBar1.Show();

           inst.ParseTheFile();
           System.Windows.Forms.MessageBox.Show("Parsing finish successfully"); 
       }
}

【问题讨论】:

  • 你应该为你的控件命名。

标签: c# progress-bar


【解决方案1】:

你可以这样做:

private void button1_Click(object sender, EventArgs e)
{
    ThreadPool.QueueUserWorkItem((obj) =>
    {
        var lines = File.ReadLines(@"D:\test.txt");
        var count = lines.Count();

        for(int i = 0; i < count; i++)
        {
            // some parse work
            Invoke(new Action(() =>
            {
                progressBar1.Value = (i * 100) / count;
            }));
        }
    });
}

在上面的示例中,它只是创建了一个后台线程,以便不阻塞 UI 线程,直到调用 Invoke 方法。 Invoke 方法是必需的,以便使用当前线程不是其所有者的 Control 进行操作。它接受一个委托,并在拥有Control 的线程上运行这个委托。

如果解析行是一项耗时的任务,您甚至可以将foreach 循环并行化。一个例子:

private void button1_Click(object sender, EventArgs e)
{
    ThreadPool.QueueUserWorkItem((obj) =>
    {
        var lines = File.ReadLines(@"D:\test.txt");
        var count = lines.Count();

        Parallel.For(0, count, i =>
        {
            // some parse work
            Invoke(new Action(() =>
            {
                progressBar1.Value = (i * 100) / count;
            }));
        });
    });
}

【讨论】:

  • @HansPassant,怎么会?所有代码都在后台线程上执行。它不会阻塞 UI 线程。
  • 它用调用请求淹没了 UI 线程,它不再做它常规的低优先级职责了。喜欢画画。
  • @HansPassant,Touché。当它运行Invoke 方法时,它将阻塞 UI 线程,非常非常短(0.1 毫秒?甚至可能更短)。但是,我仍然认为这比一直阻塞整个 UI 线程要好。你也没有注意到短暂的冻结(至少我没有)。
  • Parser 类发生了什么?为什么要在 GUI 类中解析?
  • @StealthRabbi,我假设 OP 知道 // some parse work 应该替换为对解析器方法的调用等 - 我不确定你所说的 GUI 类是什么意思?
【解决方案2】:

通常你应该继续写一些你已经尝试过的东西。 由于我认为您更多地处于 *begining" 方面,因此我建议您查看 BackgroundWorker 及其 ProgressChanged 事件/系统(这里有一个 intro 给它)。

当然,您必须将 ParseTheFile 代码移入其中。

对于更高级的东西,有几个选项:

  • ParseTheFile(例如Action)添加一个用于设置进度的参数
  • 从您的 ParseTheFile 返回一个 IObservable 以指示进度
  • 使用ParseTheFile 正在使用的一些静态服务来指示进度(不建议)
  • ...(我相信其他人会找到更多选择)

(请注意,如果您使用另一个线程,大多数这些选项都需要使用Control.Invoke 来返回您的 UI-Thread 以设置进度条值 - 如果文件是这样,我建议您使用另一个线程大)

首先,我会选择后台工作人员 - 恕我直言,如果您不想在第一次运行时使用 SOLID(设计模式/原则),那很好 ;)

【讨论】:

    【解决方案3】:

    只需使用数学来计算百分比 喜欢:

    //While Reading
    NumOfLines++;
    int Percentage = (NumOfLines * 100) / TotalLines ;
    ProgressBar.Value = Percentage;
    

    并且可能把 int.ParseTheFile();进入后台工作人员和/或线程内。

    【讨论】:

      猜你喜欢
      • 2012-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-29
      • 2011-05-18
      • 2018-04-21
      • 2019-12-05
      相关资源
      最近更新 更多