views:

811

answers:

3

Hi,
i want to use a background thread for the process of loading the XML data, possibly with a progress bar to let the user know that the application is actively doing something. i have written this code through searching the net.
i want to load a XML tree in treeview on winform when a user cliks a Browse button. In case of a large XML file the winform freezes.So to let the user know that in background the work is going on i want to add a progress bar.i have used a background worker here.

But it is raising an exception of System.ArgumentException showing this message "The URL cannot be empty.\r\nParameter name: url" on xmlDocument.Load(txtFileName.Text); this line.
My xml file is in correct format and is at the proper location where i selected. But i am unable to find the cause of this exception. Can you please help out or tell me the correction in my code?
Thanks....

       private void btnBrowse_Click(object sender,EventArgs e)
        {
            bgWorker1.RunWorkerAsync();
            StripProgressBar.Value = 0;
            toolStripStatusLabel1.Text = "Browsing for a  Xml file";

            if (open.ShowDialog(this) == DialogResult.OK)
            {
                txtFileName.Text = open.FileName;
                initiatingTree(open.FileName); //this variable gives the name of selected file
            }
            while (this.bgWorker1.IsBusy)
            {
                StripProgressBar.Increment(1);
                // Keep UI messages moving, so the form remains
                // responsive during the asynchronous operation.
                Application.DoEvents();
            }
        }//Browse button      
        private void bgWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            xmlDocument = new XmlDocument();
            Thread.Sleep(5000);
            xmlDocument.Load(txtFileName.Text);
            btnBrowse.Enabled = false;
        }
        private void bgworker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
         {
             // Set progress bar to 100% in case it's not already there.
             StripProgressBar.Value = 100;
             if (e.Error == null)
             {
                 MessageBox.Show(xmlDocument.InnerXml, "Download Complete");
             }
             else
             {
                 MessageBox.Show("Failed to download file");
             }
             // Enable the Browse button and reset the progress bar.
             this.btnBrowse.Enabled = true;
             StripProgressBar.Value = 0;
             toolStripStatusLabel1.Text = "work finished processing request.";  
         }//workerCompleted
+4  A: 

You're starting the asynchronous process immediately when the user clicks "Browse", by calling

bgWorker1.RunWorkerAsync();

This calls the DoWork method of your background worker, which sleeps for 5 seconds, and pulls the value from txtFileName.Text whether or not the user has completed their entry in the FileOpenDialog.

You'd be better off moving the byWorker1.RunWorkerAsync() (and the busy waiting) into the if (open.ShowDialog(this) == DialogResult.OK) block.

    private void btnBrowse_Click(object sender,EventArgs e)
    {
        StripProgressBar.Value = 0;
        toolStripStatusLabel1.Text = "Browsing for a  Xml file";

        if (open.ShowDialog(this) == DialogResult.OK)
        {
            txtFileName.Text = open.FileName;
            initiatingTree(open.FileName); 

            bgWorker1.RunWorkerAsync();

            while (this.bgWorker1.IsBusy)
            {
                StripProgressBar.Increment(1);
                // Keep UI messages moving, so the form remains
                // responsive during the asynchronous operation.
                Application.DoEvents();
            }
        }
    }

For these kinds of problems, it can be helpful to put a breakpoint right where the file is going to get loaded, and see what the value is when that happens... you might notice that it's getting called with an empty string.

You might also consider the version of RunWorkerAsync that takes a parameter; you could pass the file in that way, instead of trying to read it asynchronously from the textbox.

And personally, I wouldn't use a loop that calls Application.DoEvents(); instead I'd return control back to the UI thread and then Invoke() onto it from the asynchronous thread to effect the progressbar updates.

Daniel LeCheminant
thanks,Still the exception remains.Please see the exception what i have put up in my question.
crazy_itgal
+1  A: 

Hi!!

When the method bgWorker1.RunWorkerAsync(); is called the event DoWork is fired.

Because the method is called in the beginning of the application, the file name text box is empty.

I hope you've understood.

arpf
A: 

Hi guys,
First of all thanks for replying. i was able to get the answer to my question.But still the exception remains.This line shows the FileNotFoundException.
xmlDocument.Load(txtFileName.Text) is trying to load the xml file from project bin/Debug folder.whereas i want that it should take up the Xml file which user has selected and is displayed in the Textbox.
Can you please tell me how to call this from RunWorkerAsync() event.
And also how to use Invoke method?
will be waiting for your reply.
Thanks & Regards.

crazy_itgal
Are you specifying the full path to the file? It will try to load from the debug directory if only the filename (without the path) is specified.
Daniel LeCheminant
No,when a user selects a xml file from FileOpenDialogue window on cliking the browse button the textbox displays the full path of the xml file selected.i am trying to fetch that full path from the textbox.
crazy_itgal