1
votes

I have very simple WinForms application which uses class that collects countries and regions from some web-service and store collected data into file. This CollectData class worked perfect in console application, and inform about each step via Console.WriteLine

My code looks like:

    public class CollectData
    {
        public string OutputFile { get; private set; }

        public CollectData(string outputFile)
        {
            OutputFile = outputFile;
        }

    public void ProceedCollectingData()
    {
        Console.WriteLine("Getting countries...");

        List<string> countries = GetWorldCountries();
        foreach (string country in countries)
        {
            Console.WriteLine("Getting regions of country: " + country);

            List<string> regions = GetCountryRegions(country);
            AppendToFile(OutputFile, country, regions);
        }
    }

        private List<string> GetWorldCountries()
        {
            List<string> list = new List<string>();
            System.Threading.Thread.Sleep(20000); // here service fills list of countries.
            return list;
        }

        private List<string> GetCountryRegions(string country)
        {
            List<string> list = new List<string>();
            System.Threading.Thread.Sleep(20000); // here service fills list of regions.
            return list;
        }

        private void AppendToFile(string outputFile, string country, List<string> regions)
        {
            // Save everything into output file.
        }
    }

and WinForm code: private void btnCollectData_Click(object sender, EventArgs e) { CollectData collectData = new CollectData(tbOutputFile.Text.Trim()); collectData.ProceedCollectingData();

        //???? what should be here
        backgroundWorker.RunWorkerAsync(collectData);
    }

    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        //???? what should be here?
    }

    private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        //???? what should be here?
    }

    private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        progressBarCountries.Value = 100;
        progressBarRegions.Value = 100;

        lblCurrentlyProgressingStatus.Text = "Done";
    }

What is wrong and what should I change in my class, what should I open, return from class methods or redevelop, what is the right way to develop and inform progressBars about internal class logic?

I seacrhed over internet and all examples are like simple "for" loop inside backgroundWorker_DoWork with Thread.Sleep, but I have different situation.

Appreciate any clarification replies! Thanks!

1
What is the exception? What about the code to fetch the lists? All I can see is a line System.Threading.Thread.Sleep(20000)?King King
"This CollectData class worked perfect in console application, and inform about each step via Console.WriteLine" The main work should be in the DoWork() handler and basically everywhere you were doing WriteLine() should be instead handled with ReportProgress() and the ProgressChanged() event.Idle_Mind
This line is instead of sending web request to web-service and read a response, then fill the listihorko

1 Answers

1
votes

General information

BackgroundWorkers are used to delegate work to a background thread so the UI thread isn't blocked.

The actual work should take place inside an eventhandler for the DoWork event. This event is called from the background worker thread and thus you must not update any UI elements directly.

The RunWorkerCompleted event is raised when the background worker is finished, i.e. when your DoWork eventhandler returns. It is raised on the thread that creates the background worker, which normally means the UI thread, and can be used to update UI controls.

And finally the ProgressChanged event is raised when you call the ReportProgress method. It is also raised on the same thread that created the background worker and you can use it to update the UI.

Your example code

You should place the code that does the actual work in the backgroundWorker_DoWork method. Instead of calling Console.WriteLine to give users feedback about the progress call backgroundWorker.ReportProgress. In the backgroundWorker_ProgressChanged method you can update the progress bars.