In passato ho usato una progress bar per uno scopo simile e ti allego qui sotto i due metodi fondamentali che ho usato ( il codice è C# ma direi che è equivalente, i metodi erano del Form su cui la progresbar risiede):
private void BarSetUp(int tot_sims)
{
progressBarSimulation.Minimum = 0;
barScale = 100 / (double)tot_sims; //barScale è una variabile del form di tipo double
progressBarSimulation.Maximum = 100;
BarUpdate(0);
}
delegate void SetRefreshCallback(int n);
private void BarUpdate(int sim)
{
if (this.progressBarSimulation.InvokeRequired)
{
SetRefreshCallback d = new SetRefreshCallback(BarUpdate);
this.Invoke(d, new object[] { sim });
}
else
{
progressBarSimulation.Value = (int)(sim * barScale);
progressBarSimulation.Refresh();
}
}
Il mio metodo update era usato in un call back da un'altro processo e per questo non ho caricato l'evento ProgressChanged ( infatti il mio update prendeva un intero solamente senza il sender). IN sostanza comunque, con un primo metodo ( che tu dovresti lanciare al click del button scarica) inizializzo i valori massimi e minimi della progressbar (condizione questa necessaria per dare un valore logico ed utilizzabile alla variabile Value della progressbar). Con il secondo, cambiavo ogni volta che volevo il valore di Value e con il refresh aggiornavo il controllo a video.
Tu dovresti quindi appena inizi il download dargli i valori MIn e max pari a 0 e 100 (se vuoi continuare a usare percentage come riferimento progress), e poi con il tuo metodo di cambi il valore e poi fai il refresh!
Per quanto riguarda la cancellazione, a aprte il fatto che non conosco CancelAsync() nel dettaglio, ma suppondo the eviti di fare una request web e non interrompe un flusso su porta già aperto. direi che finchè non premi Ok sulla messageBox non passi all'istruzione ProgressBa.value = 0;
Non ho idea di come lo farebbe un purista,ma io associerei al form un timer che ticka ogni secondo quando un download è attivo (in pratica che parte ogni volta che premi Download - quindi il primo bottone sul suo click) e controlla una variabile globale bool chiamata per esempio downloadToBeCanceled, che sta sempre a false. Viene messa a true quando premi il pulsante cancella e al prossimo tick del timer entri in un'istruzione if che ferma il download (probabilmente con un invoke callback visto che il processo sta su un worker).
UN'ultima nota sul secondo metodo che ti ho postato sopra: contiene un grosso if che lo divide in due: se entri nell'if significa che il processo da cui vuoi manipolare il controllo è diverso dal processo corrente che governa il form, allora questo fa in modo che sia il form ad invocare di nuovo il metodo Update. Quando questo viene chiamato una seconda volta dal Form a questo punto non entra nell'if ed esegue le due linee vere e proprie (senza dare eccezioni strane dovute al cross thread) e setta la proprietà value ed esegue il refresh().
Spero aiuti
ciao
Alessandro Parma
Programmazione multipla scoposta con prognosi ancora da definirsi