Benutzer mit den meisten Antworten
DownloadFileAsync() warten bis abgeschlossen?

Frage
-
Hallo zusammen,
neben meiner Frage zu der Maximalgröße einer Queue habe ich noch eine weitere Frage.
Und zwar lade ich die Dateien über DownloadFileAsync() herunter (Status mit Progressbar wird in aufpoppendem neuen Form dargestellt).
Mein Problem ist jetzt nur, wenn mein Programm diese Dateien herunterlädt, läuft die Main GUI weiter und versucht bereits Dinge auszuführen, die nicht ausgeführt werden können ohne die geladenen Dateien.
Meine Frage wäre, gibt es eine Möglichkeit dem Programm zu sagen, das die Main GUI warten soll, bis der Download sämtlicher Dateien abgeschlossen ist?
Bin dankbar für jede Hilfe.
Viele Grüße aus Stuttgart
Christian Holzwarth
Antworten
-
In deiner anderen Frage Download Queue Limit? habe ich ein kurzes Beispiel gepostet, wie ich das meine.
Wenn dein Code wirklich so aussieht, kann es auch nicht funktionieren. Du unternimmst nichts, wenn
if (_downloadUrls.Count == 0)
ist. Im Beispiel der anderen Frage rufst du im Click-Handler StartDownloads auf. Beim Kommentar Alles herunter geladen musst du den Code einfügen, der ausgeführt werden soll, wenn alle Dateien herunter geladen wurden.
Zu der if-Abfrage, du musst auch prüfen ob alle Dateien vollständig herunter geladen wurden. D.h. du musst für jede herunter geladene Datei einen Counter hoch zählen. (counter in meinem Beispiel) Im DownloadFileCompleted-Eventhandler prüfst du dann auch noch diese Zahl.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.- Als Antwort markiert Christian Holzwarth Sonntag, 19. Januar 2014 23:02
Alle Antworten
-
Hallo,
die WebClient-Klasse hat das DownloadFileCompleted-Event. Dieses wird ausgelöst, wenn der Download einer Datei abgeschlossen wurde (nur für asynchrone Downloads). Die Klasse hat je nach Verwendung auch noch mehr Events.Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke. -
Hi,
du kannst die Task Parallel Library für ein solches Vorgehen (TPL) nutzen und dann folgendermaßen vorgehen:
Task[] tasks = new Task[2] { Task.Factory.StartNew(() => MethodA()), Task.Factory.StartNew(() => MethodB()) }; //Blocke bis alle Tasks beendet sind Task.WaitAll(tasks);
Dabei wird aber der gesamte Main-Thread angehalten. Also friert deine Main UI ein. Ein ähnliches Beispiel, dass zu deinem Download Beispiel passt, findest du unter:
http://blogs.msdn.com/b/pfxteam/archive/2010/05/04/10007557.aspx
Alternativ dazu kannst du auch nur die Komponenten deiner Main UI so lange deaktivieren, bis keine Tasks mehr laufen. Das liegt ganz an dir.
Gruß Markus
- Bearbeitet Zorro14 Donnerstag, 16. Januar 2014 10:35
-
Hallo,
@Koopakiller: Von diesen Events wusste ich bereits, allerdings habe ich jetzt nicht herausfinden können das ich durch diese irgendwie das Hauptfenster (meine Main Klasse) "anhalten" kann. So das dieses erst fortsetzt wenn alle Dateien heruntergeladen sind.
Die Funktion async/await habe ich entdeckt die dies (angeblich) lösen könnte, allerdings verstehe ich nicht genau wie ich diese anzuwenden habe.
@Markus: Was wäre in diesem Fall das Main UI? Der Download wird ausgelöst sobald man in diesem Programm (WinForms) auf einen Button drückt. Sobald der Download startet öffnet sich ein neues Form Fenster und zeigt den aktuellen Downloadstatus an. Allerdings macht das Hauptfenster (mit dem Button) einfach weiter, egal ob bereits alles heruntergeladen wurde, oder nicht (kommt natürlich zu FileNotFound Exception etc.). Mein Ziel wäre es das Hauptfenster (mit dem Button) während dem Download sozusagen zu "pausieren" das die Ausführung dieser Klasse so lange angehalten wird bis sämtliche Dateien heruntergeladen sind. Natürlich soll das Form Fenster das den Status anzeigt nicht einfrieren.
Ist dies in ungefähr verständlich bzw. realisierbar ;) ?
Viele Grüße aus Stuttgart
Christian Holzwarth -
Sobald du den bzw. die Downloads gestartet hast, machst du einfach nichts mehr. Im Eventhandler zählst du dann die fertig herunter geladenen Dateien. Sobald alle da sind, machst du dann weiter.
Die GUI anzuhalten, das man nichts mehr drücken kann, ist so, wie wenn du synchron herunter lädst.
async und await gibt es aber C# 5.0 (.NET 4.5). Anwenden kann man diese so:
async void btnClick(object sender, RoutedEventArgs e) { await DoSome();//Eine Asynchrone Methode wird aufgerufen //GUI bleibt reakitionsfähig //Nachfolgende Zeilen werden erst ausgeführt, wenn DoSome() vollständig ausgeführt wurde. }
Das alles aber von jetzt auf gleich zu verstehen ist ziehmlich schwer. Zumal await bei mehreren Asynchronen Downloads diese nur nacheinander zulassen würde.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke. -
Ja gibts es am einfachsten ist es ein Synchornisationspunkt zu setzen und wenn der Download durch ist dann im DownloadFileCompleted Event einfach den Syncpunkt setzen.
Beispiel siehe http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396%28v=vs.85%29.aspx
Falls du noch hilfe dabei brauchst einfach melden.
- Bearbeitet Brian Dahl Donnerstag, 16. Januar 2014 15:33
-
Sobald du den bzw. die Downloads gestartet hast, machst du einfach nichts mehr. Im Eventhandler zählst du dann die fertig herunter geladenen Dateien. Sobald alle da sind, machst du dann weiter.
Die GUI anzuhalten, das man nichts mehr drücken kann, ist so, wie wenn du synchron herunter lädst.
async und await gibt es aber C# 5.0 (.NET 4.5). Anwenden kann man diese so:
async void btnClick(object sender, RoutedEventArgs e) { await DoSome();//Eine Asynchrone Methode wird aufgerufen //GUI bleibt reakitionsfähig //Nachfolgende Zeilen werden erst ausgeführt, wenn DoSome() vollständig ausgeführt wurde. }
Das alles aber von jetzt auf gleich zu verstehen ist ziehmlich schwer. Zumal await bei mehreren Asynchronen Downloads diese nur nacheinander zulassen würde.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.Hmm,
mein Download Code sieht ja derzeit so aus:
#region Download private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e) { ctime = stopwatch.ElapsedMilliseconds; current = e.BytesReceived; int spe = ((int)(((current - previous) / (double)1024) / ((ctime - ptime) / (double)1000))); String speed = ((int)(((current - previous) / (double)1024) / ((ctime - ptime) / (double)1000))).ToString() + " KB/s"; Program.status.progressBar.Value = e.ProgressPercentage; Program.status.progressPercentLBL.Text = Program.status.progressBar.Value + " %"; Program.status.speedLBL.Text = speed; } private void DownloadFile() { if (_downloadUrls.Any()) { WebClient download = new WebClient(); Program.status.progressBar.Value = 0; string savePath = (string)mqver.GetValue("SavePath"); var url = _downloadUrls.Dequeue(); fileName = url.Substring(url.LastIndexOf("/") + 1, (url.Length - url.LastIndexOf("/") - 1)); if (index == 0) { index = _downloadUrls.Count + 1; } Program.status.currentData.Text = "Download: " + fileName; download.DownloadProgressChanged += ProgressChanged; download.DownloadFileCompleted += client_DownloadFileCompleted; download.Credentials = new NetworkCredential("", ""); if (!Directory.Exists(savePath)) { Directory.CreateDirectory(savePath); } download.DownloadFileAsync(new Uri(url), @"" + savePath + "\\" + fileName); } } private void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { string savePath = (string)mqver.GetValue("SavePath"); if (e.Error != null) { // handle error scenario throw e.Error; } if (e.Cancelled) { // handle cancelled scenario } if (_downloadUrls.Count == 0) {
} DownloadFile(); } #endregion
Im Moment lautet meine Abfrage im DownloadFileCompletet Event ja "if (_downloadUrls.Count == 0)".
Das Problem ist ja, das er in diesem Moment nur herunterladen soll. Buttons und Textfelder sind im Main UI schon vorher deaktiviert worden. Nur wird im Main UI zuerst meine Klasse DownloadFile aufgerufen und direkt danach die Klasse die das "eigentliche" Programm startet. Nur zu dieser Zeit sind die Dateien noch nicht auf dem lokalen Rechner vorhanden. Und wie kann ich jetzt sagen das er das Programm nicht starten soll, bevor _downloadUrls.Count nicht gleich 0 ist?
Im Moment wirkt es so als ob dies einfach ignoriert wird, da er ja sofort weiter macht indem er das Programm startet.
Viele Grüße aus Stuttgart <br/> Christian Holzwarth
-
Ja gibts es am einfachsten ist es ein Synchornisationspunkt zu setzen und wenn der Download durch ist dann im DownloadFileCompleted Event einfach den Syncpunkt setzen.
Beispiel siehe http://msdn.microsoft.com/en-us/library/system.threading.eventwaithandle%28v=vs.110%29.aspx
Falls du noch hilfe dabei brauchst einfach melden.
Hmm wie wäre dieser denn zu nutzen? Bin noch relativer Neuling in C# und arbeite mich gerade so gut es geht ein ;)Viele Grüße aus Stuttgart <br/> Christian Holzwarth
-
In deiner anderen Frage Download Queue Limit? habe ich ein kurzes Beispiel gepostet, wie ich das meine.
Wenn dein Code wirklich so aussieht, kann es auch nicht funktionieren. Du unternimmst nichts, wenn
if (_downloadUrls.Count == 0)
ist. Im Beispiel der anderen Frage rufst du im Click-Handler StartDownloads auf. Beim Kommentar Alles herunter geladen musst du den Code einfügen, der ausgeführt werden soll, wenn alle Dateien herunter geladen wurden.
Zu der if-Abfrage, du musst auch prüfen ob alle Dateien vollständig herunter geladen wurden. D.h. du musst für jede herunter geladene Datei einen Counter hoch zählen. (counter in meinem Beispiel) Im DownloadFileCompleted-Eventhandler prüfst du dann auch noch diese Zahl.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.- Als Antwort markiert Christian Holzwarth Sonntag, 19. Januar 2014 23:02
-
In deiner anderen Frage Download Queue Limit? habe ich ein kurzes Beispiel gepostet, wie ich das meine.
Wenn dein Code wirklich so aussieht, kann es auch nicht funktionieren. Du unternimmst nichts, wenn
if (_downloadUrls.Count == 0)
ist. Im Beispiel der anderen Frage rufst du im Click-Handler StartDownloads auf. Beim Kommentar Alles herunter geladen musst du den Code einfügen, der ausgeführt werden soll, wenn alle Dateien herunter geladen wurden.
Zu der if-Abfrage, du musst auch prüfen ob alle Dateien vollständig herunter geladen wurden. D.h. du musst für jede herunter geladene Datei einen Counter hoch zählen. (counter in meinem Beispiel) Im DownloadFileCompleted-Eventhandler prüfst du dann auch noch diese Zahl.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.Viele Grüßee aus Stuttgart
Christian Holzwarth