如何在加载xml文件时使用进度条

本文关键字:文件 加载 xml | 更新日期: 2023-09-27 18:14:34

我想在加载远程xml文件时显示进度条。我在Visual c# 2008 Express Edition中使用Windows Application Form。

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");
        for (int x = 0; x < node.Count; x++ )
        {
            textBox2.Text = node[x].InnerText;
            progressbar1.Value = x;
        }
    }

上面的代码不能显示进度条加载。请给我建议一些代码。提前感谢

如何在加载xml文件时使用进度条

你到底想让进度条反映什么?是下载文件(因为它很大)还是处理文件?

反映处理文件的进度条

你的进度条不会改变,因为你的方法是同步的——在它结束时不会发生任何其他事情。BackgroundWorker类就是为解决这类问题而设计的。它以异步方式完成主要工作,并且能够报告已经更改的进度。下面是如何更改tour方法来使用它:

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);
}

现在,主要部分:

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;
}

反映下载文件的进度条

尝试使用HttpWebRequest获取文件作为流。

// 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;

现在您知道了这个XML文件的长度。然后,您必须从流异步读取内容(BackgroundWorkerStreamReader是一个好主意)。使用myStream.PositionmyStreamLenght计算进度。

我知道我不是很具体,但我只是想把你在正确的方向。我认为把这些都写在这里没有意义。这里有一些链接,可以帮助你处理StreamBackgroundWorker:

进度条在这里不起作用,因为这都是"同步"代码。Click事件阻止UI更新

有两个解。

您可以创建一个后台线程来处理XML文件,后台线程将进度报告给前台。我建议使用BackgroundWorker,但在此之前还有很多东西要学习。

一个更简单的解决方案,虽然不是最优的,是通过在每次进度更新后调用Application.DoEvents()来刷新表单。这应该只是一个短期的解决方案,因为如果任务不是很快,那么您的应用程序可能会冻结。

两种解决方案都有一个缺点——当你的进度条被刷新时,你的应用程序也会处理任何事件。因此,您必须在任务处理期间手动禁用UI,并在完成后重新启用它。

不久前,我为这个问题创建了一个可重用的解决方案。我创建了一个"ProgressDialog",它接受一个委托。进度对话框执行委托,并捕获进度,更新进度条,甚至计算剩余时间。使用ProgressDialog的好处是,我可以在"modal"模式下显示对话框,这阻止了对主UI的访问,甚至阻止了Click事件的完成。不幸的是,我没有任何代码可以分享,只有一个想法。

问题是您正在使用窗口线程,并且窗口不能重新绘制,直到您完成button1_Click。

使用BackgroundWorker,你可以通过调用BackgroundWorker报告进度。ReportProgress

首先,它可能运行得太快了,你看不到-如果你在测试,试着在那里放一个Sleep,但进一步说,它不更新的原因是你正在处理,而这发生在主UI正在使用的同一个线程上。

你可以让程序通过调用Application.DoEvents()来处理所有事件,但是这样做,你也重新处理了用户可能点击过的任何东西(包括这个按钮)——所以如果你想DoEvents并确保你不会处理额外的工作,在方法启动时禁用表单。

总而言之,一个更好的模型是线程化你的工作,并在计时器或回调上更新进度条。