How can I use backgroundworker to download multiple images and display them in pictureBox ?

sharon glipman 441 Reputation points
2020-12-15T13:03:09.183+00:00
using System;  
using System.Collections.Generic;  
using System.ComponentModel;  
using System.Data;  
using System.Drawing;  
using System.IO;  
using System.Linq;  
using System.Net;  
using System.Text;  
using System.Threading;  
using System.Threading.Tasks;  
using System.Windows.Forms;  
using HtmlAgilityPack;  
  
namespace SatImages  
{  
    public partial class Form1 : Form  
    {  
        private int counter = 0;  
  
        public Form1()  
        {  
              
  
            InitializeComponent();  
  
            progressBar1.Value = 0;  
            progressBar1.Maximum = 10;  
  
            backgroundWorker1.RunWorkerAsync();  
        }  
  
        private void Form1_Load(object sender, EventArgs e)  
        {  
  
        }  
  
        private void Download()  
        {  
            var wc = new WebClient();  
            wc.BaseAddress = "https://myimages";  
            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();  
  
            var temp = wc.DownloadData("/en");  
            doc.Load(new MemoryStream(temp));  
  
            var secTokenScript = doc.DocumentNode.Descendants()  
                .Where(e =>  
                       String.Compare(e.Name, "script", true) == 0 &&  
                       String.Compare(e.ParentNode.Name, "div", true) == 0 &&  
                       e.InnerText.Length > 0 &&  
                       e.InnerText.Trim().StartsWith("var region")  
                      ).FirstOrDefault().InnerText;  
            var securityToken = secTokenScript;  
            securityToken = securityToken.Substring(0, securityToken.IndexOf("arrayImageTimes.push"));  
            securityToken = secTokenScript.Substring(securityToken.Length).Replace("arrayImageTimes.push('", "").Replace("')", "");  
            var dates = securityToken.Trim().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);  
            var scriptDates = dates.Select(x => new ScriptDate { DateString = x });  
            foreach (var date in scriptDates)  
            {  
                string img = "https://myimages" + date.DateString;  
  
                Image image = DownloadImageFromUrl(img);  
                image.Save(@"d:\images\" + counter + ".jpg");  
  
                counter++;  
            }  
        }  
  
        public class ScriptDate  
        {  
            public string DateString { get; set; }  
            public int Year  
            {  
                get  
                {  
                    return Convert.ToInt32(this.DateString.Substring(0, 4));  
                }  
            }  
            public int Month  
            {  
                get  
                {  
                    return Convert.ToInt32(this.DateString.Substring(4, 2));  
                }  
            }  
            public int Day  
            {  
                get  
                {  
                    return Convert.ToInt32(this.DateString.Substring(6, 2));  
                }  
            }  
            public int Hours  
            {  
                get  
                {  
                    return Convert.ToInt32(this.DateString.Substring(8, 2));  
                }  
            }  
            public int Minutes  
            {  
                get  
                {  
                    return Convert.ToInt32(this.DateString.Substring(10, 2));  
                }  
            }  
        }  
  
        public System.Drawing.Image DownloadImageFromUrl(string imageUrl)  
        {  
            System.Drawing.Image image = null;  
  
            try  
            {  
                System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(imageUrl);  
                webRequest.AllowWriteStreamBuffering = true;  
                webRequest.Timeout = 30000;  
  
                System.Net.WebResponse webResponse = webRequest.GetResponse();  
  
                System.IO.Stream stream = webResponse.GetResponseStream();  
  
                image = System.Drawing.Image.FromStream(stream);  
  
                webResponse.Close();  
            }  
            catch (Exception ex)  
            {  
                return null;  
            }  
  
            return image;  
        }  
  
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)  
        {  
            Download();  
            backgroundWorker1.ReportProgress(counter);  
        }  
  
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)  
        {  
            progressBar1.Value = e.ProgressPercentage;  
        }  
  
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  
        {  
  
        }  
    }  
}  

It's downloading fine the images and display the overall downloading of the images in the progressBar. So I guess I'm using fine the report progress for the percentages?

The main problem is that I want that while it's downloading the images to save them like now to the hard disk but also in real time to display them in pictureBox1 with some delay not downloading delay but displaying it in the pictureBox1 delay so it will looks like animated in the pictureBox1.

I tried to add this line inside the foreach :

pictureBox1.Image = image;  

foreach (var date in scriptDates)  
            {  
                string img = "https://myimages" + date.DateString;  
  
                Image image = DownloadImageFromUrl(img);  
                pictureBox1.Image = image;  
                image.Save(@"d:\images\" + counter + ".jpg");  
  
                counter++;  
            }  

but then it's throwing exception message in green say the object is in use :

System.InvalidOperationException: 'Object is currently in use

and the exception happens only when adding this pictureBox1 line.

The main goal is to display the images download progress in the progressBar1 with percentages counting up to 100 in the middle of the progressBar1 , saving the images to the hard disk and show the images in pictureBox1 like animated gif in real time when image has downloaded display it in the pictureBox1 then the next one in a loop.

Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,911 questions
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.