我想在加载Remote xml文件时显示进度条。我在Visual C#2008 Express Edition中使用Windows应用程序表单。
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;
}
}
以上代码无法显示进度条加载..请建议我一些代码。提前致谢
答案 0 :(得分:9)
您希望通过进度条反映出什么?而是下载文件(因为它很大)或处理文件?
您的进度条不会更改,因为您的方法是同步的 - 单位结束时不会发生任何其他事情。 BackgroundWorker
课程专为此类问题而设计。它以异步方式执行主要工作,并能够报告进度已更改。以下是如何更改巡视方法以使用它:
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文件的长度。然后你必须异步读取流中的内容(BackgroundWorker
和StreamReader
是一个好主意)。使用myStream.Position
和myStreamLenght
计算进度。
我知道我不是很具体,但我只是想让你朝着正确的方向前进。我认为在这里写下所有这些内容是没有意义的。在这里,您可以使用链接来帮助您处理Stream
和BackgroundWorker
:
答案 1 :(得分:2)
进度条在这里不起作用,因为这是全部&#34;同步&#34;码。 Click
事件阻止UI更新。
有两种解决方案。
您可以创建后台线程来处理XML文件,后台线程将进度报告给前台。我建议您使用BackgroundWorker
,但在此之前还有很多东西需要学习。
更简单的解决方案(尽管不是最佳的)是在每次进度更新后调用Application.DoEvents()
来刷新表单。这应该只被视为短期解决方案,因为如果任务不快,那么您的应用程序可能会冻结。
这两种解决方案都有缺点 - 当您的进度条刷新时,您的应用程序也会处理任何事件。因此,您必须在处理任务时手动禁用UI,并在完成后重新启用它。
前段时间,我为这个问题创建了一个可重用的解决方案。我创建了一个&#34; ProgressDialog&#34;需要代表。进度对话框执行委托,捕获进度,更新进度条,甚至计算剩余时间。使用ProgressDialog的好处是我可以在&#34;模态&#34;中显示对话框。模式,阻止访问主UI,甚至阻止Click
事件完成。
不幸的是,我没有任何代码可以分享,只是想法。
答案 2 :(得分:1)
问题是你正在使用窗口线程,并且在完成button1_Click之前窗口无法重绘。
使用BackgroundWorker,您可以通过调用backgroundworker.ReportProgress
来报告进度答案 3 :(得分:0)
首先,它可能会让你看得太快 - 如果你正在测试它,试着把Sleep放在那里,但是,进一步说,它没有更新的原因是你正在处理并且发生在同一个线程上主UI正在使用。
您可以让程序通过调用Application.DoEvents()来处理所有事件,但通过这样做,您还可以重新处理用户可能点击的任何内容(包括此按钮) - 所以如果您想要DoEvents并确保您不要最终处理其他工作,在方法启动时禁用表单。
所有这一切,一个更好的模型是线程你的工作并更新计时器或回调的进度条。