Przekazanie zmiennej z pętli for

0

Witam.
Mam problem z przekazaniem zmiennej z pętli for do funkcji aktualizującej progressbar.

 using System;
using System.Net;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace gallery_ripper
{
	/// <summary>
	/// Description of MainForm.
	/// </summary>
	public partial class MainForm : Form
	{
		public MainForm()
		{

			InitializeComponent();

		}
		
		public void Button1Click(object sender, EventArgs e)
		{
			string 	url 	= boxUrl.Text;
			int		start 	= int.Parse(boxStart.Text);
			int		end		= int.Parse(boxEnd.Text);
			string	ltt		= boxl10.Text;
			string	gtt		= boxg10.Text;
			int		i;
			string	xadres;
			string	xfname;
			
			for(i=start; i< (end + 1); i++)
			{
				
				if(i<10)
				{
					xadres = url + ltt + i + ".jpg";
					xfname = i + ".jpg";				
				} else {
					xadres = url + gtt + i + ".jpg";
					xfname = i + ".jpg";
				}
				//MessageBox.Show(xadres);
				pobierz(xadres, xfname);
				
			}
			
			MessageBox.Show("Zakonczono", "Gallery Ripper", MessageBoxButtons.OK, MessageBoxIcon.Information);
			
			
			
		}
		
		public void pobierz(string adres, string filename)
        {
            WebClient webClient = new WebClient();
 
            webClient.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(webClient_DownloadFileCompleted);
            webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
 
            try
            {
                webClient.DownloadFileAsync(new Uri(adres), filename);
            }
            catch (WebException e)
            {
            	MessageBox.Show("Downloading ERROR!");
            	this.Close();
            }
        }
 
		
        public void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            progressItem.Value = int.Parse(e.ProgressPercentage.ToString());
            progressItem.Refresh();
        }
 
        
        public void webClient_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
        	progressOverall.Value = (i * 100) / end;
		progressOverall.Refresh();
        }
	}
}

Chciałbym po prostu w ostatniej funkcji odwołać się do zmiennej i oraz end, które były deklarowane przy wciskaniu buttona.
Jednak kompilator twierdzi, że Nazwa "end" nie istnieje w bieżącym kontekście.
W jaki sposób mogę "zrobić" te zmienne globalnymi ?

1

Zadeklaruj te zmienne jako pola klasy a nie wewnątrz funkcji.

0

Dało by radę jasniej ? Może jakaś podpowiedź/przykład ? Zaczynam z # i nie chciałbym się zrazić na wstępie. :-) Z góry dzięki za pomoc.

Edit: Jeśli dobrze rozumiem Twoją wypowiedź, masz na myśli abym zadeklarował zmienne bezpośrednio w klasie a w funkcji dopiero przypisał im konkretne wartości odczytane z pól ?

0

Polecam poczytać o zasięgu zmiennych :)


class Sample {
  int a = 10;
  
  void foo() {
  int i = 0;
  a = 5; // widoczna
  for() {
    i = 5; //widoczna
   }
 }

  void bar() {
    i = 10; //niewidoczna
    a = 15; //widoczna
  }

}
 

Edit: Tak, dobrze myślisz ;)

0

Dzięki wielkie, bardzo pomogłeś.
By nie zakładać kolejnego zbędnego watku mam jeszcze jedno pytanie.
Dlaczego pętla for wykonuje się cała niemal natychmiast zamiast pobrac jeden plik, potem drugi itd...
Niemal natychmiast dostaję info, że zakończono a pliki dopiero się pobierają. Chciałbym aby pobierał się każdy plik, potem update głównego progressbar-a i kolejny...

0

Bo tak działa pętla for ;) Pętla nie będzie "czekać" aż funkcja pobierz zakończy swoje działanie, tylko przechodzi do kolejnej iteracji.

0

Rozumiem że nie mogę inaczej zmusić pętli by zaczekała na zakończenie funkcji ?

0

Nie chcę mieszać bo nie wiem jak działa funkcja webClient.DownloadFileAsync(new Uri(adres), filename);. Ja bym w funkcji webClient_DownloadFileCompleted sprawdzał czy są jeszcze jakieś pliki do pobrania, i wtedy dopiero zaczynał pobieranie kolejnego pliku ;) Ale ja się nie znam :)

0

Jest to jakies rozwiązanie. Jeszcze raz dzięki za pomoc.

0

Ludzie, co Wy mówicie ?! Skoro jest wywoływana metoda, która w nazwie ma "async", to znaczy, że pobieranie jest realizowane w TLE ! Dlatego for nie czeka na zakończenie pobierania. Jak będziecie do pobierania używać funkcji "sync" a nie "async", to for będzie czekał aż pobieranie pliku się zakończy przed rozpoczęciem pobierania kolejnego pliku...

0

Po nazwie funkcji wnioskuję że pliki są pobierane asynchronicznie ;) Czyli po prostu musisz sprawdzać czy wszystkie pliki są pobrane i dopiero wtedy wywołać msg boxa, że pobrano wszystkie pliki. Tak samo aktualizować progress bar na podstawie wartości każdego z plików.

Edit: Racja :) spróbuj użyć metody DownloadFile()

0

Niestety posiadam 2 progressbary, metoda DownloadFile "zamraża" wykonywanie do czasu zakończenia pobierania pliku i uniemożliwia aktualizację pierwszego paska, który pokazuje postep pobierania aktualnego pliku.
Posłużyłem się Twoją sugestią i udało mi się rozwiązać problem likwidując pętlę a dając warunek i iterację do ostatniej funkcji i działa jak należy.

using System;
using System.Net;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace gallery_ripper
{
	/// <summary>
	/// Description of MainForm.
	/// </summary>
	public partial class MainForm : Form
	{
		public MainForm()
		{
			
			InitializeComponent();
			
			
		}
		
		string		url;
		int			start;
		int			end;
		string		ltt;
		string		gtt;
		int			i;
		string		xadres;
		string		xfname;
		
		public void Button1Click(object sender, EventArgs e)
		{
			url 	= boxUrl.Text;
			start 	= int.Parse(boxStart.Text);
			end		= int.Parse(boxEnd.Text);
			ltt		= boxl10.Text;
			gtt		= boxg10.Text;
			i		= start;
			
				
				xadres = url + ltt + i + ".jpg";
				xfname = i + ".jpg";
				//MessageBox.Show(xadres);
				pobierz(xadres, xfname);
				
					
			
		}
		
		public void pobierz(string adres, string filename)
        {
            WebClient webClient = new WebClient();
 
            webClient.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(webClient_DownloadFileCompleted);
            webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
 
            try
            {
                webClient.DownloadFileAsync(new Uri(adres), filename);
            }
            catch (WebException e)
            {
            	MessageBox.Show("Downloading ERROR!");
            	this.Close();
            }
        }
 
		
        public void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
             
            progressItem.Value = int.Parse(e.ProgressPercentage.ToString());
            progressItem.Refresh();
        }
 
        
        public void webClient_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
        	
        	//MessageBox.Show(i + " / " + end);
        	progressOverall.Value = (i * 100) / end;
			progressOverall.Refresh();
			i++;
			if (i>end)
			{
				zakoncz();
			} else {
				
				if (i<10)
				{
					xadres = url + ltt + i + ".jpg";
					xfname = i + ".jpg";
				} else {
					xadres = url + gtt + i + ".jpg";
					xfname = i + ".jpg";
				}
				pobierz(xadres, xfname);
				
			}
        }
        
        void zakoncz()
        {
        	MessageBox.Show("Zakonczono", "Gallery Ripper", MessageBoxButtons.OK, MessageBoxIcon.Information);
        	Application.Exit();
        }
	}
}
 

P.S.
zaraz założę nowy wątek z nowym problemem, nie bijcie :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1