progress bar and backgroundworker in C#

2019-06-02 16:19发布

问题:

Currently I am working on a project which need to consume large amount data from web services, There is service class sending input date to the server and get back the result, due to it time consuming process, it is required to user combined progressbar and backgroundworker to show user the process percentage. I have browsing quite a few sample code on this topic, but still could not figure out the best way to do it. Would you please help, My code is following,

private  MyCollection[] callWebService(string[] Inputs, string method)
{
    List<string> results = new List<string>();
    string fiel dNames = ""; // todo - fix this if nothing left in loop
    int sizeOfArray = 500;
    for (int i = 0; i < Inputs.Length; i = i + sizeOfArray)
    {
        string[] outputRecords;
        int errorCode;
        string errorString;
        string[] thisFiveHundred = createSubArray(Inputs, i, sizeOfArray);


        iq.NameValuePair[] namevaluepairs = new iq.NameValuePair[0];
        fieldNames = iqOfficeWebservice.BatchStan(method, thisFiveHundred, null, "",        out outputRecords, out errorCode, out  errorString);
        results.AddRange(outputRecords);
    }
    results.ToArray();
    IAddress[] formattedResults = convertStringsToInputs(fieldNames, results);
    return formattedResults;
}

回答1:

    private void cmdButton_Click(object sender, EventArgs e)
    {
        BackgroundWorker worker = new BackgroundWorker();
        worker.WorkerReportsProgress = true;
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
        worker.RunWorkerAsync();
    }

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

        for (int i = 0; i < 101; i++)
        {
            worker.ReportProgress(i);
            System.Threading.Thread.Sleep(1000);
        }
    }

    private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        lblProgress.Text = ("Progress: " + e.ProgressPercentage.ToString() + "%");
    }

Additional info can be found here.



回答2:

Apart from the technical implementation in WPF or Winforms for example there is an essential aspect to consider.

  • Do you get feedback of the progress from the web services?

If not, you are likely not able to predict correctly the time the web service will need. This will depend on factors you cannot influence (like server load, network traffic, ...). In this case a progress bar is not recommended as it will give the user a weird experience.

Then you have options like displaying an text information that the request could take minutes and display a progress with an IsIndeterminate flag set (WPF) to show continuous progress feedback. A sandhour cursor is not an option as you are using a background thread.

An alternative is to break down the big request into smaller parts for which you can report progress.



回答3:

I've just put together a variation of Adil's answer that encapsulates the work and updates, as well as properly detaching events and disposing of the worker. Please upvote Adil's answer if you upvote mine.

    private void cmdButton_Click(object sender, EventArgs e)
    {
        var worker = new BackgroundWorker();
        worker.WorkerReportsProgress = true;

        DoWorkEventHandler doWork = (dws, dwe) =>
        {
            for (int i = 0; i < 101; i++)
            {
                worker.ReportProgress(i);
                System.Threading.Thread.Sleep(100);
            }
        };

        ProgressChangedEventHandler progressChanged = (pcs, pce) =>
        {
            lblProgress.Text = String.Format("Progress: {0}%", pce.ProgressPercentage);
        };

        RunWorkerCompletedEventHandler runWorkerCompleted = null;
        runWorkerCompleted = (rwcs, rwce) =>
         {
             worker.DoWork -= doWork;
             worker.ProgressChanged -= progressChanged;
             worker.RunWorkerCompleted -= runWorkerCompleted;
             worker.Dispose();
             lblProgress.Text = "Done.";
         };

        worker.DoWork += doWork;
        worker.ProgressChanged += progressChanged;
        worker.RunWorkerCompleted += runWorkerCompleted;

        worker.RunWorkerAsync();
    }