[英]How Do I Show Image Loading Progress in progress-bar c#
我想知道如何在win窗体的进度栏中显示图像加载进度。
我的代码是
private void Form2_Load(object sender, EventArgs e)//load form and get profile and avatar
{
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
label2.Text = "Avatar Loaded";
}
private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)//showing progress
{
if (InvokeRequired)
{
BeginInvoke(new Action(() => backgroundWorker1_ProgressChanged(sender, e)));
}
else
{
if (progressBarX1.Value != e.ProgressPercentage)
{
progressBarX1.Value = e.ProgressPercentage;
progressBarX1.Refresh();
}
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)//loading avatar
{
WebClient wc = new WebClient();
Stream stream = wc.OpenRead("http://avatar.nimbuzz.com/getAvatar?jid=" + textBox1.Text);
pictureBox1.Image = (Image.FromStream(stream));
}
图像成功加载,但在进度栏中未显示任何进度
您的代码的问题在于,在辅助线程的上下文中调用了backgroundWorker1_ProgressChanged(),但UI更新只能在UI线程(主线程)内完成。 在您的情况下,您必须致电:
progressBarX1.Value = e.ProgressPercentage;
在UI线程中。 有很多方法可以执行此操作,但是一个简单的方法是使用InvokeReqzired()检查您是否在UI线程中,然后再不调用BeginInvoke()将该命令的执行发送到UI- / main-线。 以下应该可以解决问题:
private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
if (InvokeRequired)
{
BeginInvoke(new Action(() => backgroundWorker1_ProgressChanged(sender, e)));
}
else
{
progressBarX1.Value = e.ProgressPercentage;
}
}
更新:我还将更改:
backgroundWorker1.RunWorkerAsync();
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
至:
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerAsync();
因此,在开始异步工作之前,已分配(因此就位)了progress事件。 否则,您可能会错过进度呼叫。
更新2:
您还需要以下行在UI线程中执行:
pictureBox1.Image = (Image.FromStream(stream));
为此,请使用BackgroundWorker的Completed事件,并使用result参数低音处理图像数据。 然后在事件处理程序中使用InvokeRequired()和BeginInvoke(),就像在Progress事件中一样。
Uodate 3:
记住保持不变是个好习惯,因为您不会因为未在UI线程中调用UI东西而崩溃;-)
尝试通过调用以下命令来强制重画控件:
progressBarX1.Refresh();
(就在您为其分配了新值之后)。
因此,progress事件中的代码如下所示:
private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
if (InvokeRequired)
{
BeginInvoke(new Action(() => backgroundWorker1_ProgressChanged(sender, e)));
}
else
{
if (progressBarX1.Value != e.ProgressPercentage)
{
progressBarX1.Value = e.ProgressPercentage;
progressBarX1.Refresh();
}
}
}
如果仍然不起作用,请检查您的主/ UI线程是否未阻塞或完全繁忙。
更新4:
只是要确保:您需要在后台工作程序上启用进度报告,并在backgroundWorker1_DoWork()中不时调用其ReportProgress()方法。 有关使用BackgroundWorker的更多信息,请参见下面的MS教程: http : //msdn.microsoft.com/zh-cn/library/cc221403(v=vs.95).aspx
在后台工作人员上启用进度报告:
backgroundWorker1.WorkerReportsProgress = true;
或使用表单设计器并将属性WorkerReportsProgress设置为True。 然后,您仍然需要不时地调用backgroundWorker1.ReportProgress()。
更新5:
好的,让我们尝试一下。 我已经检查了MS的一些参考文档,因此,在后台工作程序ProgressChanged和Completed事件的情况下,您不需要BeginInvoke()它们,因为MS已经为您完成了此操作。
private void Form2_Load(object sender, EventArgs e)
{
getto();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.ProgressChanged -= backgroundWorker1_ProgressChanged;
backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
backgroundWorker1.RunWorkerCompleted -= backgroundWorker1_Completed;
backgroundWorker1.RunWorkerCompleted += backgroundWorker1_Completed;
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
using (var wc = new WebClient())
{
wc.DownloadProgressChanged += (sender, e) => backgroundWorker1.ReportProgress(sender, e);
using (var stream = wc.OpenRead("http://avatar.nimbuzz.com/getAvatar?jid=" + textBox1.Text))
{
e.Result = (Image.FromStream(stream));
}
}
}
private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
progressBarX1.Value = e.ProgressPercentage;
progressBarX1.Refresh();
}
private void backgroundWorker1_Completed(object sender, DoWorkEventArgs e)
{
pictureBox1.Image = e.Result;
}
好吧,我将使用WebClient中的ProgressChanged事件来获取下载进度实际距离的结果。 然后,您将无法从backgroundworker的线程中保存它,因此在拥有文件时必须执行此操作。
更新
private BackgroundWorker bgw;
private void Form1_Load(object sender, EventArgs e)
{
bgw = new BackgroundWorker();
bgw.DoWork += bgw_DoWork;
bgw.WorkerReportsProgress = true;
bgw.RunWorkerCompleted += bgw_RunWorkerCompleted;
bgw.ProgressChanged += bgw_ProgressChanged;
bgw.RunWorkerAsync();
}
void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
pictureBox1.Image = (Image)e.Result;
}
void bgw_DoWork(object sender, DoWorkEventArgs e)
{
WebClient wc = new WebClient();
wc.DownloadProgressChanged += wc_DownloadProgressChanged;
Stream stream = wc.OpenRead("" + textBox1.Text);
e.Result = (Image.FromStream(stream));
}
void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
bgw.ReportProgress(e.ProgressPercentage);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.