How to use Progress bar during loading an xml File

前端 未结 4 1899
伪装坚强ぢ
伪装坚强ぢ 2021-01-06 05:32

I want to show progress bar during loading a Remote xml file. I am using Windows Application Form in Visual C# 2008 Express Edition.

private void button1_Cl         


        
相关标签:
4条回答
  • 2021-01-06 06:02

    The progress bar doesn't work here, because this is all "synchronous" code. The Click event blocks the UI from updating.

    There are 2 solutions.

    You can create a background thread to process the XML file, and the background thread reports progress to the foreground. I'd recommend using a BackgroundWorker, but there's a lot to learn before you do this.

    An easier solution, although not optimal, is to refresh the form by calling Application.DoEvents() after each progress update. This should only be considered a short-term solution, because if the task isn't quick, then your application could appear to freeze.

    Both solutions have a drawback - when your progress bar is refreshed, your application will also process any events. Therefore, you must manually disable your UI while the task is processing, and re-enable it when finished.

    A while back, I created a reusable solution for this issue. I created a "ProgressDialog" that takes a delegate. The progress dialog executes the delegate, and captures the progress, updates its progress bar, and even calculates the time remaining. The benefit of using the ProgressDialog is that I can show the dialog in "modal" mode, which blocks the access to the main UI, and even prevents the Click event from finishing.
    Unfortunately, I don't have any code to share, just the idea.

    0 讨论(0)
  • 2021-01-06 06:03

    The problem is that you are using window thread, and the window can not been redrawn, until you finish button1_Click.

    Use BackgroundWorker, you can report progress by calling backgroundworker.ReportProgress

    0 讨论(0)
  • 2021-01-06 06:09

    What exacly do you want to reflect by progress bar? Rather downloading the file (because it's big) or processing the file?

    Progress bar reflecting processing file

    Your progress bar doesn't change because your method is synchronous - nothing else will happen unit it ends. BackgroundWorker class is designed perfectly for this kind of problems. It does main work in an asynchronous manner and is able to report that progress has changed. Here is how to change tour method to use it:

    private void button1_Click(object sender, EventArgs e)
    {
        string text =  textBox1.Text;
        string url = "http://api.bing.net/xml.aspx?AppId=XXX&Query=" + text + "&Sources=Translation&Version=2.2&Market=en-us&Translation.SourceLanguage=en&Translation.TargetLanguage=De";
    
        XmlDocument xml = new XmlDocument();
        xml.Load(url);
        XmlNodeList node = xml.GetElementsByTagName("tra:TranslatedTerm");
    
        BackgroundWorker worker = new BackgroundWorker();
    
        // tell the background worker it can report progress
        worker.WorkerReportsProgress = true;
    
        // add our event handlers
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.RunWorkerCompleted);
        worker.ProgressChanged += new ProgressChangedEventHandler(this.ProgressChanged);
        worker.DoWork += new DoWorkEventHandler(this.DoWork);
    
        // start the worker thread
        worker.RunWorkerAsync(node);
    }
    

    Now, the main part:

    private void DoWork(object sender, DoWorkEventArgs e)
    {
       // get a reference to the worker that started this request
       BackgroundWorker workerSender = sender as BackgroundWorker;
    
       // get a node list from agrument passed to RunWorkerAsync
       XmlNodeList node = e.Argument as XmlNodeList;
    
       for (int i = 0; x < node.Count; i++)
       {
           textBox2.Text = node[i].InnerText;
           workerSender.ReportProgress(node.Count / i);
       }
    }
    
    private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // do something after work is completed     
    }
    
    public void ProgressChanged( object sender, ProgressChangedEventArgs e )
    {
        progressBar.Value = e.ProgressPercentage;
    }
    

    Progress bar reflecting downloading file

    Try using HttpWebRequest to get the file as a stream.

    // Create a 'WebRequest' object with the specified url. 
    WebRequest myWebRequest = WebRequest.Create(url); 
    
    // Send the 'WebRequest' and wait for response.
    WebResponse myWebResponse = myWebRequest.GetResponse(); 
    
    // Obtain a 'Stream' object associated with the response object.
    Stream myStream = myWebResponse.GetResponseStream();
    
    long myStreamLenght = myWebResponse.ContentLength;
    

    So now you know the length of this XML file. Then you have to asynchronously read the content from stream (BackgroundWorker and StreamReader is a good idea). Use myStream.Position and myStreamLenght to calculate the progress.

    I know that I'm not very specific but I just wanted to put you in the right direction. I think it doesn't make sense to write about all those things here. Here you have links that will help you dealing with Stream and BackgroundWorker:

    0 讨论(0)
  • 2021-01-06 06:11

    First it might be going too fast for you to see - try putting a Sleep in there if you're testing that, but further, the reason it's not updating is that you're processing and that happens on the same thread that the main UI is using.

    You can have the program process all events by calling Application.DoEvents() but by doing so, you also reprocess anything the user might have clicked on (including this button) - so if you want to DoEvents and make sure you don't end up processing additional work, disable the form when the method starts.

    All that said, a better model is to thread your work and update the progress bar on a timer or a callback.

    0 讨论(0)
提交回复
热议问题