我想知道如何以获胜形式在进度条中显示图片加载进度。
我的代码是
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));
}
图像加载成功但未在进度条中显示任何进度
答案 0 :(得分:0)
您的代码的问题是在工作线程的上下文中调用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参数对图像数据进行低音。然后在eventhandler中使用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-Tutorial:http://msdn.microsoft.com/en-us/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;
}
答案 1 :(得分:0)
好吧,我会使用WebClient中的ProgressChanged事件来获取实际下载进度的结果。然后你就无法从后台工作者的线程中保存它,所以当你有文件时你必须这样做。
<强>已更新强>
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);
}