后台工作者的奇怪行为和多个进度条c#

时间:2013-03-28 15:10:11

标签: c# progress-bar backgroundworker

我尝试模拟一个长时间运行的过程。在我的应用程序中,我使用背景并动态添加进度条。当我点击开始按钮然后进程开始并在面板上添加进度条。如果我只点击一次然后一切正常,但如果我点击两次或更多,那么进度条的数量会被添加,但最后一个进度条的进度会增加,最后其他进度条的进度会突然增加。

我希望添加任意数量的进度条,所有进度条应同时处理,而不是最后一个,最后一个。一切都应该像许多进程在他们自己的上下文中同时运行一样。这是我的代码,我希望如果有人看到它然后他们可以理解哪里是缺陷。请帮我修复最后添加进度条进度增加的缺陷。如果可能的话,运行我的代码并查看问题。

public partial class Form2 : Form
{
    MyBackgroundWorker backgroundWorker1 = null;
    Dictionary<string, string> dct = new Dictionary<string, string>();
    public Form2()
    {
        InitializeComponent();
    }

    private void Form2_Load(object sender, EventArgs e)
    {

    }

    private void btnStart_Click(object sender, EventArgs e)
    {
        backgroundWorker1 = new MyBackgroundWorker();
        backgroundWorker1.WorkerReportsProgress = true;   
        backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
        backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
        backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
        backgroundWorker1.RunWorkerAsync(txtNumber.Text);

    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        string strID = DateTime.Now.ToString("yyyyMMdd") + DateTime.Now.ToString("hhmmss")+DateTime.Now.Millisecond.ToString();
        MyBackgroundWorker tmpBg = (sender as MyBackgroundWorker);
        tmpBg.Name = "bg_" + strID;

        ProgressBar pb = new ProgressBar();
        pb.Minimum = 0;
        pb.Maximum = 100;
        pb.Name = "pb_" + strID;
        pb.Width = txtNumber.Width;
        this.BeginInvoke((MethodInvoker)delegate
        {
            flowLayoutPanel1.Controls.Add(pb);
        });

        dct.Add(tmpBg.Name, pb.Name);

        int input = int.Parse(e.Argument.ToString());
        for (int i = 1; i <= input; i++)
        {
            Thread.Sleep(2000);
            backgroundWorker1.ReportProgress(i * 10);
            if (backgroundWorker1.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
        }
    }

    // This event handler updates the progress bar. 
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        MyBackgroundWorker tmpBg = (sender as MyBackgroundWorker);
        string strName = tmpBg.Name;

        if (!string.IsNullOrEmpty(strName))
        {
            strName = strName.Substring(3);
            ProgressBar pb = (ProgressBar)this.flowLayoutPanel1.Controls.Find(("pb_" + strName), true)[0];
            pb.Value = e.ProgressPercentage;
        }
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        MyBackgroundWorker tmpBg = (sender as MyBackgroundWorker);
        string strName = tmpBg.Name;
        strName = strName.Substring(3);
        ProgressBar pb = (ProgressBar)this.flowLayoutPanel1.Controls.Find(("pb_" + strName), true)[0];
        pb.Value = 100;
        //MessageBox.Show("Done");
    }

}

    public class MyBackgroundWorker : System.ComponentModel.BackgroundWorker
        {
            public MyBackgroundWorker()
            {
            }

            public MyBackgroundWorker(string name)
            {
                Name = name;
            }

            public string Name { get; set; }
        }

更新部分

 private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MyBackgroundWorker tmpBg = (sender as MyBackgroundWorker);
            string strName = tmpBg.Name;
            strName = strName.Substring(3);
            ProgressBar pb = (ProgressBar)this.flowLayoutPanel1.Controls.Find(("pb_" + strName), true)[0];
            //pb.Value = 100;
            //MessageBox.Show("Done");
            flowLayoutPanel1.Controls.Remove(pb);
        }

1 个答案:

答案 0 :(得分:0)

我认为我按照你想要的方式工作。

  1. 在ProgressChanged中,我以另一种方式获得进度条。

  2. 在DoWork中,我以百分比和当前的backgroundWorker报告进度。

  3. 我删除了Thread.Sleep因为我认为它导致了问题,在Console.WriteLine中添加DoWork以减慢程序速度(否则它比{{1}快}渲染)

    ProgressBar