0

時間のかかるルーチンの 1 つを呼び出すたびに、ポップアップしてプログレス バーを表示するフォームを作成しました。私はUpdateProgressメソッドを通じてルーチンの進行状況をフィードします。

バックグラウンドワーカーを使用して、ユーザーがフォームを移動し、このフォームが更新されている間もビジネスを続けられるようにしています。ただし、ルーチンが完了するまでフォームがロックされ、すぐにプログレス バーが 100% まで上昇して終了します (本来の動作です)。UpdateProgressプログレスバーは、メソッドへの呼び出しの進行状況とともに更新されるはずです。

ここで何が間違っていますか?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace myNameSpace
{
    public partial class ProgressIndicator : Form
    {
        int progressPercentage;

        public ProgressIndicator()
        {
            InitializeComponent();
        }

        void progressUpdater_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            // update the UI with appropriate fields
            progressBar.Value = e.ProgressPercentage;
            labelCommunicating.Text = "In progress: " + e.ProgressPercentage + "% complete";
        }

        void progressUpdater_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.Close();
        }

        void progressUpdater_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            while (true)
            {
                if (progressPercentage >= 100)
                {
                    break;
                }

                worker.ReportProgress(progressPercentage);

                Thread.Sleep(100);
            }
        }

        public void UpdateProgress(int progressPercentage)
        {
            this.progressPercentage = progressPercentage;
        }

        private void ProgressIndicator_Load(object sender, EventArgs e)
        {
            BackgroundWorker progressUpdater = new BackgroundWorker();
            progressUpdater.WorkerReportsProgress = true;
            progressUpdater.WorkerSupportsCancellation = true;
            progressUpdater.DoWork += new DoWorkEventHandler(progressUpdater_DoWork);
            progressUpdater.RunWorkerCompleted += new RunWorkerCompletedEventHandler(progressUpdater_RunWorkerCompleted);
            progressUpdater.ProgressChanged += new ProgressChangedEventHandler(progressUpdater_ProgressChanged);

            progressUpdater.RunWorkerAsync();
        }
    }
}
4

2 に答える 2

1

これはとてつもない解決策のようなにおいがします。あなたの問題はwhile loop. ただし、より良いアプローチは、たとえばProgressBar、UI をブロックせずに単純に更新することです。Invoke();

Invoke(new myUpdate(updateProgress), pval);//call invoke whenever you need to update the progress bar assuming pval is an integer with the value to update with. This could be in a thread for instance.

//declare this as a class level delegate
private delegate void myUpdate(int progress);

//method to update progress bar
private void updateProgress(int progress)
{
    progressBar.Value = progress;
}
于 2012-07-30T22:11:44.220 に答える
0

この方法でプロセスを作成できるため、呼び出しを Invoke メソッドにラップする必要はありません。

//delegate method
private delegate void updateProgressDelegate(int progress);

//actual method
private void updateProgress(int progress)
{
    if(this.InvokeRequired)
    {
        this.Invoke(new updateProgressDelegate(updateProgress), progress);
    }
    else
    {
        progressBar.value = progress;
    }
}
于 2012-07-30T22:42:10.190 に答える