简体   繁体   English

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

[英]How Do I Show Image Loading Progress in progress-bar c#

I want to know how to show image loading progress in progress-bar in win form. 我想知道如何在win窗体的进度栏中显示图像加载进度。

my code is 我的代码是

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

The image loads successfully but do not show any progress in progress-bar 图像成功加载,但在进度栏中未显示任何进度

The problem with your code is that backgroundWorker1_ProgressChanged() is called in the context of the worker thread but UI updates can only be done within the UI thread (main thread). 您的代码的问题在于,在辅助线程的上下文中调用了backgroundWorker1_ProgressChanged(),但UI更新只能在UI线程(主线程)内完成。 In your scenario you must call: 在您的情况下,您必须致电:

progressBarX1.Value = e.ProgressPercentage;

within the UI thread. 在UI线程中。 There are many ways how to do this but a simple one is to use InvokeReqzired() to check if you are in the UI thread and you are not then call BeginInvoke() to send the execution of that command to the UI-/main-thread. 有很多方法可以执行此操作,但是一个简单的方法是使用InvokeReqzired()检查您是否在UI线程中,然后再不调用BeginInvoke()将该命令的执行发送到UI- / main-线。 The following should do the trick: 以下应该可以解决问题:

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
  if (InvokeRequired)
  {
    BeginInvoke(new Action(() => backgroundWorker1_ProgressChanged(sender, e)));
  }
  else
  {
    progressBarX1.Value = e.ProgressPercentage;
  }
}

Update: I would also change: 更新:我还将更改:

    backgroundWorker1.RunWorkerAsync();
    backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

to: 至:

    backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
    backgroundWorker1.RunWorkerAsync();

so the progress event is assigned (and therefore in place) before starting the asynchronous work. 因此,在开始异步工作之前,已分配(因此就位)了progress事件。 Otherwise you may miss a progress call. 否则,您可能会错过进度呼叫。

Update 2: 更新2:

You also need the following line to execute in the UI thread: 您还需要以下行在UI线程中执行:

pictureBox1.Image = (Image.FromStream(stream));

To do so use the Completed event of BackgroundWorker and bass the image data using the result parameter. 为此,请使用BackgroundWorker的Completed事件,并使用result参数低音处理图像数据。 Then in the eventhandler use InvokeRequired() and BeginInvoke() just like in the Progress event). 然后在事件处理程序中使用InvokeRequired()和BeginInvoke(),就像在Progress事件中一样。

Uodate 3: Uodate 3:

Remeins unchanged is good as you don't get a crash because of not calling UI stuff in the UI thread ;-) 记住保持不变是个好习惯,因为您不会因为未在UI线程中调用UI东西而崩溃;-)

Try to force a repaint on the control by calling: 尝试通过调用以下命令来强制重画控件:

progressBarX1.Refresh();

(just after you assigned a new value to it). (就在您为其分配了新值之后)。

So the code in the progress event looks like this: 因此,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();
  }
}

} }

If that still doesn't work check that your main/UI thread is not blocked or totally busy. 如果仍然不起作用,请检查您的主/ UI线程是否未阻塞或完全繁忙。

Update 4: 更新4:

Just to make sure: you need to enable progress-reporting on the background worker and call its ReportProgress() method from time to time within the backgroundWorker1_DoWork(). 只是要确保:您需要在后台工作程序上启用进度报告,并在backgroundWorker1_DoWork()中不时调用其ReportProgress()方法。 See the following MS-Tutorial for more information on usage of the BackgroundWorker: http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx 有关使用BackgroundWorker的更多信息,请参见下面的MS教程: http : //msdn.microsoft.com/zh-cn/library/cc221403(v=vs.95).aspx

Enabling progress reporting on a backgroundworker: 在后台工作人员上启用进度报告:

backgroundWorker1.WorkerReportsProgress = true;

or use the form-designer and set the property WorkerReportsProgress to True. 或使用表单设计器并将属性WorkerReportsProgress设置为True。 Then you still need to call the backgroundWorker1.ReportProgress() from time to time. 然后,您仍然需要不时地调用backgroundWorker1.ReportProgress()。

Update 5: 更新5:

Ok, lets give it a complete try. 好的,让我们尝试一下。 I've checked some reference docs from MS so in case of the backgroundworker ProgressChanged and Completed events you don't need to BeginInvoke() them as MS does this already for you. 我已经检查了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;
}

Well, i would use the ProgressChanged Event from a WebClient to get the result of how far the download progress actually is. 好吧,我将使用WebClient中的ProgressChanged事件来获取下载进度实际距离的结果。 Then you can't save it from the thread of the backgroundworker, so you gotta do this when you have the file. 然后,您将无法从backgroundworker的线程中保存它,因此在拥有文件时必须执行此操作。

UPDATED 更新

    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