如何在进度条c#中显示图像加载进度

时间:2014-07-25 10:52:22

标签: c# progress-bar backgroundworker

我想知道如何以获胜形式在进度条中显示图片加载进度。

我的代码是

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

图像加载成功但未在进度条中显示任何进度

2 个答案:

答案 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);
    }
相关问题