如何从其他类更新进度条?

时间:2012-06-28 20:12:44

标签: c# .net progress-bar

我有一个用c#编写的命令行工具(我有源代码),我在visual studio 2010中制作gui。在gui我想更新进度条以反映工具操作的进度。我如何从工具内部发出已取得进展的信号并更新进度条? 我正在做的一些简化示例代码。

private void doThings_Click(object sender, EventArgs e)
{
  myToolInstance.doWorkThatNeedsToReportProgress();
}

该工具正在进行的工作是一系列函数调用,通常在30左右。我想在每次完成其中一个时更新进度条。

2 个答案:

答案 0 :(得分:12)

在包含进度条的表单中创建公共属性或公共方法

public void SetProgress(int progress)
{
    progressBar.Progress = progress;
}

现在您可以使用

更新进度条
myForm.SetProgress(50);

另一种方法是在某处发生ProgressChanged事件,并让表单订阅此事件。

public class Tool {
    public event Action<int> ProgressChanged;

    private void OnProgressChanged(int progress) 
    {
        var eh = ProgressChanged;
        if (eh != null) {
            eh(progress);
        }
    }

    public void DoSomething()
    {
        ...
        OnProgressChanged(30);
        ...
    }
}

在表格中你会有这样的东西

private Tool _tool;

public MyForm () // Constructor of your form
{
    _tool = new Tool();
    _tool.ProgressChanged += Tool_ProgressChanged;
}

private void Tool_ProgressChanged(int progress)
{
    progressBar.Progress = progress;
}

答案 1 :(得分:0)

尽管我遇到了类似的问题,但我还是想在这里分享我的解决方案。

通常,由于计算复杂性,我有一种方法将异步运行。输入参数之一是进度条本身。
由于ProgressBar为可空类型,因此在调用该方法时不是强制性的。
在方法内部,我在其调度程序中执行进度条前进-在许多情况下,该方法将在拥有进度条的其他线程上运行。为了处理进度条的无效可能性,我使用了nullable运算符:

private string MyMethod(int input, ProgressBar progressBar)
{
    while(!done)
    {
        // Do the hard work.

        progressBar?.Dispatcher.Invoke(() => progressBar.Value++);
    }
}

现在,我需要在调用该方法之前设置进度条Maxiumim,并且必须将其设置为预期的长度。

有些人可能会说,每次我需要提高进度栏时,都会给调度员打电话造成效率低下。是的,我同意这一点,但是这完全取决于我们需要执行多少步骤。这就是为什么我要运行一些快速基准测试的原因。

就我而言,我有超过300,000(三十万)个步骤(每个步骤是将一些数据格式化为字符串并将该字符串写入文件)。我的参考是运行没有进度条更新的方法。

  • 更新进度条每个步骤使运行时间延长了超过 2,000%(长20倍)
  • 更新进度条每10步使运行时间延长了超过 250%(长了两倍半)
  • 更新进度栏每100步使运行时间延长了大约 15%(大约延长了1/8)
  • 更新进度条每1000步使运行时间延长了大约 3%(边际差异)

在进度条为240像素宽的情况下,我已经确定最大进度条为300左右,并相应地对其进行更新,从而获得了非常流畅的动画,而没有明显的性能损失。