繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM