Search code examples
c#backgroundworker

Background worker within a function in c# wpf


I have made a simple gui in C# wpf, (sorry I can't show the GUI because my reputation is below 10)

It's consist of richtextbox and some other controls. Umm... this application will read a file then display the file contents to richtextbox line by line while reading the file using background worker. The function that read the file is like this :

    public int parse_persoFile2(string fname, BackgroundWorker worker, DoWorkEventArgs e)
    {
        if (fname == null) return -1;
        System.IO.StreamReader ifs;
        ifs = new System.IO.StreamReader(fname);

        int max = (int)e.Argument;
        int p = 0;

        while (ifs.Peek() != -1)
        {
            string tempData = ifs.ReadLine();

            if (tempData.Contains("CMD=5107") || tempData.Contains("CMD=5106") || tempData.Contains("CMD=5102"))
            {

                //field.AppendText(tempData.Remove(tempData.LastIndexOf('\\')).Remove(0, 4) + "\r\n");
                //field.AppendText("--------\r\n");
                //System.Threading.Thread.Sleep(500);
                string data = tempData.Remove(tempData.LastIndexOf('\\')).Remove(0, 4) + "\r\n";
                worker.ReportProgress(p, data);
            }

            p++;

        }
        worker.ReportProgress(100);
        return 0;
    }

As we can see, I'm using backgroundworker in this function to get the string readed from file then send that string to reportprogress in order to be displayed in richtextbox. As a note that persoFile2 function is made from another object in my program... :-)

Then for the rest, I have made the doWork function, worker_progressChanged, and worker_RunWorkerCompleted to make backroundWorker works correctly. Those codes are like this :

    private void doWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker wrk = sender as BackgroundWorker;
        parser.parse_persoFile2(fileName, wrk, e);
    }

    private void proggChanged(object sender, ProgressChangedEventArgs e)
    {
        if(e.UserState != null)
        mRTB.AppendText(e.UserState.ToString());
    }

    private void completed(object sender, RunWorkerCompletedEventArgs e)
    {
        MessageBox.Show("Ok....");

    }

Umm.... When I run this program, it looks that my richtextbox is not prints the string line by line from the file, but it prints it just once at the end... :-3, .. Nah that's my real problem here. I have read this article http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx, but still have no idea.... :3


Solution

  • If you call the ReportProgress method too rapidly, it's possible that the UI thread will not have a chance to process the "progress" and update appropriately before the BackgroundWorker is hitting it again.

    private void doWork(object sender, DoWorkEventArgs e)
    {
        var wrk = sender as BackgroundWorker;
    
        // obviously you wouldn't really do this :)
        while(true)
            wrk.ReportProgress(0);
    }
    

    To see the effect you're looking expecting, you could set an artificial "pause" in your DoWork event, in order to give the UI time to update appropriately:

    private void doWork(object sender, DoWorkEventArgs e)
    {
        var wrk = sender as BackgroundWorker;
    
        var p = 0;
        while(true)
        {
            wrk.ReportProgress(p++);
            Thread.Sleep(100);
        }
    }
    

    As for your situation, if the code is executing that quickly, you may not actually need to be executing it in a separate thread.

    Alternatively, you could update your UI to say "Please wait. Loading...", then do everything you need to do in the BackgroundWorker, and just return the final result back to the UI at the end.