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

C# 如何从其他类更新进度条?,c#,.net,progress-bar,C#,.net,Progress Bar,我有一个用c#编写的命令行工具(我有它的源代码),我正在VisualStudio2010中为它制作gui。在gui中,我想更新进度条以反映工具操作的进度。我如何从工具内部发出信号,表示已取得进展,并更新进度条? 我正在做的一些简化的示例代码 private void doThings_Click(object sender, EventArgs e) { myToolInstance.doWorkThatNeedsToReportProgress(); } 该工具正在完成的工作是一系列函数

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

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

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

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

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);
        ...
    }
}

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

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

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

        progressBar?.Dispatcher.Invoke(() => progressBar.Value++);
    }
}
现在,我需要在调用该方法之前设置进度条
Maxiumim
,并且必须将其设置为预期长度

有人可能会说,每当我需要推进进度条时,我都会给调度员打电话,导致效率低下。是的,我同意这一点,但这取决于我们需要走多少步。这就是为什么我运行了一些快速基准测试

在我的例子中,我有超过300000(三十万)个步骤(每个步骤都是将一些数据格式化为字符串并将该字符串写入文件)。在没有更新进度条的情况下运行该方法是我的参考

  • 更新进度条每一步都会使运行时间延长超过2000%(延长20倍)
  • 每第10步更新一次进度条会使运行时间延长250%以上(两倍半)
  • 每第100步更新一次进度条会使运行时间延长约15%(延长约1/8)
  • 每第1000步更新一次进度条会使运行时间延长约3%(边际差异)

由于我的进度条宽度为240像素,我已确定进度条的最大宽度约为300像素,并相应地对其进行更新,以获得非常平滑的动画效果,而不会造成明显的性能损失。

您是否可以控制命令行工具的源代码?该工具当前是否以任何方式指示进度?怎么做?进步是由你努力完成的事情反映出来的。您需要找到反映手头任务的变量,该变量可以被监视并更新到进度栏。如果你用细节来编辑你的文章会有帮助的。你能给我们一些你的代码,并指出哪个部分需要进度条吗?另外,您在什么框架(WPF,Winforms?)中构建GUI?您如何实例化您的工具?什么UI-Forms或WPF?为什么命令行工具需要保留?你就不能把这些都添加到UI中吗?它仍然是.NET和C#。问题是进度数据来自外部工具(在不同的进程中运行)。但它可以工作,因为我可以(并且确实)获取该工具的源代码。
private string MyMethod(int input, ProgressBar progressBar)
{
    while(!done)
    {
        // Do the hard work.

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