6

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

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

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

4

2 回答 2

16

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

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;
}
于 2012-06-28T20:16:59.470 回答
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 像素,并相应地对其进行更新,从而获得非常流畅的动画效果,而不会造成明显的性能损失。

于 2019-10-09T10:58:50.043 回答