【问题标题】:The right way to implement a progressbar in C#C#中实现进度条的正确方法
【发布时间】:2011-06-01 16:44:38
【问题描述】:

我正在学习 winforms,我为自己设定了一个简单的目标,即制作一个从空到满的进度条。这是我的畸形尝试:

public partial class Form1 : Form
{
    static BackgroundWorker bw = new BackgroundWorker();

    public Form1()
    {
        InitializeComponent();
        bw.DoWork += bw_DoWork;
        bw.RunWorkerAsync();
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        for(int i=0; i<100; ++i)
        {
            progressBar1.PerformStep();
            Thread.Sleep(10);
        }
    }
}

我很确定Thread.Sleep() 是应受谴责的。我如何在这里避免它?

【问题讨论】:

  • 试试here。或here。或here.
  • 或者,如果你想做一些激动人心的事情,尝试运行一个算法并使用 StopWatch 对象从该算法测量一个步骤,然后你可以计算出该步骤将执行多少次,这样你就可以获得 TotalTime ,并基于此使用你的数学技能来获得当前阶段的百分比,所以我认为这会让你满意。

标签: c# winforms multithreading backgroundworker


【解决方案1】:

您已经做得几乎正确。 BackgroundWorker 已经内置了报告进度的机制。

public Form1()
{
    bw1.WorkerReportsProgress = true;
    bw1.ProgressChanged += bw1_ProgressChanged;
    bw1.DoWork += bw1_DoWork;

    bw1.RunWorkerAsync();
}

private void bw1_DoWork(object sender, DoWorkEventArgs e)
{
    var worker = sender as BackgroundWorker;

    while (workNotDone)
    {
        //Do whatever work
        worker.ReportProgress(CalculateProgressDonePercentage());
    }
}

private void bw1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    //This is called on GUI/main thread, so you can access the controls properly
    progressBar.Value = e.ProgressPercentage;
}

当然,除非您只是尝试为进度条设置动画而不实际报告任何进度,在这种情况下,您可能应该只使用 Marquee 类型,它会自动滚动进度条而不做任何事情。或者只是使用Thread.Sleep() 的后台线程。

【讨论】:

    【解决方案2】:

    在后台线程中,调用Thread.Sleep没有任何问题。
    如果这是一个占位符,您可以放心地将其替换为实际工作。

    但是,您不能直接从后台线程操作 ProgressBar(或任何其他控件)。
    相反,您应该使用BackgroundWorker 的内置进度功能来控制进度条。

    如果您只是想为无意义的进度条设置动画,则应使用 WinForms Timer 而不是 BackgroundWorker

    【讨论】:

      【解决方案3】:

      如果您只是想在执行耗时任务时测试更新 UI,Thread.Sleep 可以。对于不平凡的程序,你总能在这里找到一些任务来代替。

      但是,您不应直接在BackgroundWorker.DoWork 内更新进度条,因为 Windows 要求更新 UI 必须在 UI 线程上调用,而不是在后台线程上调用。相反,调用BackgroundWorker.ReportProgress 方法。始终在 BackgroundWorker.ProgressChanged 事件中更新 UI。

      您可以在此处查看示例:http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

      【讨论】:

        猜你喜欢
        • 2022-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-03
        • 2018-02-26
        • 2010-11-18
        • 1970-01-01
        相关资源
        最近更新 更多