0

私の主な問題は、リクエストごとにflowLayoutPanel1にプログレスバーを動的に追加するときです。次に、backgroundWorker1_ProgressChangedイベントから右のプログレスバーの値を増やすにはどうすればよいですか

ユーザーがスタート ボタンをクリックすると、バックグラウンド ワーカーの RunWorkerAsync 関数が呼び出されます。問題ありません。ここで私はサンプルコードを書いており、私の問題を示しています。

私のフォームには、1 つのテキスト ボックス、1 つのボタン、および FlowDirection がトップダウンの 1 つの flowLayoutPanel1 があります。

ユーザーがテキストボックスに任意の URL を入力して開始ボタンをクリックすると、BackGroundWorker でファイルのダウンロードが開始され、flowLayoutPanel1 に進行状況バーが動的に 1 つ追加されます。一度に10個のファイルをダウンロードできます。したがって、ユーザーが10個のURLを1つずつ入力して送信ボタンをクリックすると、10個のファイルがバックグラウンドでダウンロードされます。

私の問題は、backgroundWorker1_ProgressChanged イベントから 10 のプログレス バーの進行状況を適切にインクリメントする方法です。別の問題は、ファイルのダウンロードが完了すると、作成されたプログレス バーがパネルから削除されることです。

これが私の完全なコードです。見て、私の仕事を達成するために何をする必要があるか教えてください。私のコードにデッドロックが発生する可能性がある問題があることがわかった場合は、デッドロックを回避する方法も教えてください。ここに私のコードがあります

public partial class Form1 : Form
    {
        static int pbCounter = 1;

        public Form1()
        {
            InitializeComponent();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            ProgressBar pb = new ProgressBar();
            if (pbCounter <= 10)
            {
                pb.Width = txtUrl.Width;
                flowLayoutPanel1.Controls.Add(pb);
                pbCounter++;

                System.ComponentModel.BackgroundWorker backgroundWorker1 = new System.ComponentModel.BackgroundWorker();

                backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
                backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
                backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

                backgroundWorker1.RunWorkerAsync();
            }
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            // Get the BackgroundWorker that raised this event.
            System.ComponentModel.BackgroundWorker worker = sender as System.ComponentModel.BackgroundWorker;

            // Assign the result of the computation
            // to the Result property of the DoWorkEventArgs
            // object. This is will be available to the  
            // RunWorkerCompleted eventhandler.
            //#e.Result = ComputeFibonacci((int)e.Argument, worker, e);
        }

        // This event handler deals with the results of the
        // background operation.
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // First, handle the case where an exception was thrown.
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
            else if (e.Cancelled)
            {
                //# "Canceled";
            }
            else
            {
                pbCounter--;
                // Finally, handle the case where the operation  
                // succeeded.
                //#resultLabel.Text = e.Result.ToString();
            }
        }

        // This event handler updates the progress bar.
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
        }

    }

私の更新部分

 public partial class Form1 : Form
    {
        static int pbCounter = 1;

        public Form1()
        {
            InitializeComponent();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            ProgressBar pb = new ProgressBar();
            if (pbCounter <= 10)
            {
                //pb.Step = 10;
                pb.Minimum = 0;
                //pb.Maximum = 100;
                pb.Width = txtUrl.Width;
                flowLayoutPanel1.Controls.Add(pb);
                pbCounter++;

                MyBackgroundWorker backgroundWorker1 = new MyBackgroundWorker();
                backgroundWorker1.pbProgress = pb;
                backgroundWorker1.WorkerReportsProgress = true;   
                backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
                backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
                backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

                backgroundWorker1.RunWorkerAsync(txtUrl.Text);
            }
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            int input = int.Parse(e.Argument.ToString());
            for (int i = 1; i <= input; i++)
            {
                Thread.Sleep(2000);
                 (sender as MyBackgroundWorker).ReportProgress(i * 10);
                 if ((sender as MyBackgroundWorker).CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
            }
        }

        // This event handler deals with the results of the 
        // background operation. 
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // First, handle the case where an exception was thrown. 
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
            else if (e.Cancelled)
            {
                //# "Canceled";
            }
            else
            {
                ProgressBar pb = (sender as MyBackgroundWorker).pbProgress;
                if (pb != null)
                {
                    //pb.Value = 100;
                    //pb.Update();

                    while (pb.Value <= pb.Maximum)
                    {
                        //Thread.Sleep(1000);
                        flowLayoutPanel1.Controls.Remove(pb);
                        break;
                    }

                }
                // Finally, handle the case where the operation  
                // succeeded.
            }
        }

        // This event handler updates the progress bar. 
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            ProgressBar pb = (sender as MyBackgroundWorker).pbProgress;
            pb.Refresh();

            //if (e.ProgressPercentage < pb.Maximum)
            //    pb.Value = e.ProgressPercentage + 10;

            pb.Value = e.ProgressPercentage ;
            Application.DoEvents();

        }

    }

public class MyBackgroundWorker : System.ComponentModel.BackgroundWorker
    {
        public ProgressBar pbProgress = null;
        public MyBackgroundWorker()
        {
        }

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

        public string Name { get; set; }
    }
4

2 に答える 2

1

これはそれを行う1つの方法です-

BackgroundWorker から継承した独自のクラスを作成し、ProgressBar 型のパブリック変数を追加します。

BackgroundWorker と Progressbar を動的に追加するたびに、progressbar オブジェクトをクラスに渡します。

あなたの派生クラス -

public class MyBackgroundWorker : BackgroundWorker
{
    public ProgressBar pbProgress = null;

    public void BackgroundWorker()
    {
    }
}

ボタン イベント コード -

private void btnStart_Click(object sender, EventArgs e)
{
    ProgressBar pb = new ProgressBar();
    if (pbCounter <= 10)
    {
        pb.Width = txtUrl.Width;
        flowLayoutPanel1.Controls.Add(pb);
        pbCounter++;

        MyBackgroundWorker backgroundWorker1 = new MyBackgroundWorker();
        backgroundWorker1.pbProgress = pb;

        backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
        backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
        backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

        backgroundWorker1.RunWorkerAsync();
    }
}

進行状況変更イベント -

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        (sender as MyBackgroundWorker).pbProgress.Value = e.ProgressPercentage;
    }
于 2013-03-28T10:50:46.543 に答える
1

最初に、フォーム インスタンスにアクセスするためのグローバル ディクショナリと GetInstance メソッドを宣言します。

public partial class Form1 : Form
{
Dictionary<String, ProgressBar> progressBars = new Dictionary<String, ProgressBar>();

static Form1 _form1 = null;

static int pbCounter = 1;

public Form1()
{
    InitializeComponent();
    _form1 = this;
}

public static Form1 GetInstance() {
    return _form1;
}

次に、取得した各URLで、それぞれに対してpbを作成する必要があります。この辞書にも追加するだけです

progressBars.Add("file1", pb1);
progressBars.Add("file2", pb2);
progressBars.Add("file3", pb3);
progressBars.Add("file4", pb4);

プログレスバーを渡すことができ、その値を手動で設定できる関数を form.cs に作成します。

public void ProgessReport(ProgressBar pb, int value) 
        {
            if (pb.InvokeRequired) 
            {
                pb.Invoke(new MethodInvoker(delegate { ProgessReport(pb, value); }));
            } else 
            {
                pb.Value = value;
            }
        }

今すぐ呼び出す必要があるファイルをダウンロードしている場所から

Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file1"], 10);
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file1"], 20);
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file1"], 100);

and when your second file downloads then

Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file2"], 10);
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file2"], 20);
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file2"], 100);

このような ..

于 2013-03-28T10:52:58.223 に答える