Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!
Werbeanzeige
Quellcode |
|
1 2 3 4 5 6 7 8 9 10 |
for (int o = 0; o < len; o++) { if (!blocked) { Data.DownloadFileAsync(new Uri(basic + links[o]), links[o]); o++; } blocked = true; } Data.Dispose(); |
Quellcode |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
void Data_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { files++; blocked = false; //Sichern der bisherigen Bytes, die empfangen wurden temp += received; if (files == len) { listBoxUpdateInfo.Items.Add("Alle Dateien erfolgreich heruntergeladen."); listBoxUpdateInfo.SelectedIndex = listBoxUpdateInfo.Items.Count - 1; counter(); } } |
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Affje« (02.08.2011, 19:48)
Hallo,Also zusammengefasst: Du hast ein Array aus Links auf Dateien und willst die parallel herunterladen?
C#-Quelltext |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
string[] links = { /* Füge deine links hier ein! */ }; WebClient[] clients = new WebClient[links.Length]; //Definiere den Handler System.ComponentModel.AsyncCompletedEventHandler downloadCompletedHandler = (s, e) => { if (e.Error != null) Console.WriteLine("Could not download file! {0}", e.Error.Message); else { KeyValuePair<byte, string> userState = (KeyValuePair<byte, string>)e.UserState; Console.WriteLine("Downloaded file {0}. Download request position: {1}", userState.Value, userState.Key); } ((WebClient)s).Dispose(); }; //Eigentlich müsste hier auch clients.Initialize() gehen. Bei mir sind danach aber alle Clients noch null ;) //Habs darum hier runter genommen. Hier werden alle clients initialisiert. Ausserdem wird der eventhandler zugewiesen. for (int i = 0; i < clients.Length; ++i) { clients[i] = new WebClient(); clients[i].DownloadFileCompleted += downloadCompletedHandler; } //'count' brauchst du eigentlich garnicht. Ich habe den mal noch hier reingeschraubt um dir zu zeigen, wie du die position //an welcher der Download gestartet wurde mitgeben kannst. byte count = 0; foreach (string link in links) { string filename = @"I:\F"+count.ToString()+Path.GetExtension(link); clients[count].DownloadFileAsync(new Uri(link), filename, new KeyValuePair<byte, string>(count++, filename)); } |
Dieser Beitrag wurde bereits 10 mal editiert, zuletzt von »Darkrel« (12.06.2011, 17:38)
Simple Antwort:
Ein WebClient unterstützt zeitgleich nur eine HTTP Request. (Ich kann dir da keine offizielle Quelle nennen, das ist nur die Standardantwort auf dein Problem wenn man 5 Minuten googelt.)
Benutze entweder mehrere Instanzen des WebClients (und speichere die natürlich so lange bis das event aufgerufen wird) oder verwende keine WebClients.
C#-Quelltext
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 string[] links = { /* Füge deine links hier ein! */ }; WebClient[] clients = new WebClient[links.Length]; //Definiere den Handler System.ComponentModel.AsyncCompletedEventHandler downloadCompletedHandler = (s, e) => { if (e.Error != null) Console.WriteLine("Could not download file! {0}", e.Error.Message); else { KeyValuePair userState = (KeyValuePair)e.UserState; Console.WriteLine("Downloaded file {0}. Download request position: {1}", userState.Value, userState.Key); } ((WebClient)s).Dispose(); }; //Eigentlich müsste hier auch clients.Initialize() gehen. Bei mir sind danach aber alle Clients noch null ;) //Habs darum hier runter genommen. Hier werden alle clients initialisiert. Ausserdem wird der eventhandler zugewiesen. for (int i = 0; i < clients.Length; ++i) { clients[i] = new WebClient(); clients[i].DownloadFileCompleted += downloadCompletedHandler; } //'count' brauchst du eigentlich garnicht. Ich habe den mal noch hier reingeschraubt um dir zu zeigen, wie du die position //an welcher der Download gestartet wurde mitgeben kannst. byte count = 0; foreach (string link in links) { string filename = @"I:\F"+count.ToString()+Path.GetExtension(link); clients[count].DownloadFileAsync(new Uri(link), filename, new KeyValuePair(count++, filename)); }
Du musst natürlich deinen Pfad noch selber anpassen und solltest anstatt von den Arrays Listen oder Dictionaries verwenden.
Du wirst ja nicht immer eine fixe Anzahl downloads haben Kannst also jeden link auf einen WebClient mappen und den entsprechenden WebClienten dann aus dem Dictionary entfernen. Wenn du das aus dem Callback raus machen willst, dann solltest du dich aber mit Threading beschäftigen oder wenn du eine simple, aber nicht ganz so effiziente Lösung willst, die Extensionmethode .AsParallel verwenden. Wenn du noch eine Progressbar willst, dann schau dir mal das entsprechende event im WebClienten an, das lässt sich sicher auch umsetzen.
Alternative Lösung (aber mehr Arbeit): Schreib dir die Funktionalität selber und direkt mit HTTP Requests.
Edit9: Ja, 9 Edits Habe den code nochmal angepasst :p
Quellcode |
|
1 |
DownloadProgressChangedEventHandler |
C#-Quelltext |
|
1 2 3 4 5 6 7 8 9 10 11 |
private void Read_Packet(string s) { if (textBox3.Dispatcher.CheckAccess()) { textBox3.Text += s; } else { textBox3.Dispatcher.BeginInvoke(DispatcherPriority.Send, new Action<string>(Read_Packet), s + "\n"); } } |
Hm naja... wie gesagt. Wenn du weisst wie gross alle Dateien gemeinsam sind, kannst du sie auch parallel herunterladen UND eine progressbar haben, die den Gesamtfortschritt anzeigt. Ich schau mir das nachher gleich mal ein wenig an.
Wie schon jemand vor mir gefragt hat: Mit was arbeitest du? Windows Forms, XNA, WPF ... was?
C#-Quelltext |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
public partial class Form1 : Form { /* Variablen */ Dictionary<string, Label> _labels; Dictionary<string, ProgressBar> _progressBars; Dictionary<string, Object> _progressBarsLocks; Dictionary<string, WebClient> _webClients; ProgressBar _totalProgressBar; Object _totalProgressBarLock = new Object(); Button _exitButton; /* Konstanten */ const int DLLeft = 10; const int DLWidth = 120; const int DLHeight = 20; const int DLStep = 25; const int DLStartTop = 40; const int ProgressBarMaxValue = 1000; const int ProgressBar_Left = 140; const int TotalProgressBarTop = 200; const int TotalProgressBarLeft = 10; const int TotalProgressBarWidth = 270; /* Konstruktor */ public Form1() { InitializeComponent(); _exitButton = new Button(); _exitButton.Text = "Exit"; _exitButton.Click += new EventHandler( (sender, args) => { this.Close(); } ); _exitButton.Left = TotalProgressBarLeft; _exitButton.Width = TotalProgressBarWidth; _exitButton.Top = 5; Controls.Add(_exitButton); _exitButton.Show(); string[] links = { /* Deine Links hier */ }; StartDownload(links); this.FormBorderStyle = FormBorderStyle.None; } /* Startet den Download aller dateien gleichzeitig und Asynchron. * Für jede Datei, die heruntergealden wird, wird eine eigene Progressbar angezeigt. * Zusätzlich wird der Gesamstatus in einer zusätzlichen Progressbar angezeigt. * * Anmerkung: Das ist kein schöner Code ;) Das Beispiel soll nur vermitteln, wie dein * Problem gelöst werden _könnte_. */ public void StartDownload(IEnumerable<string> links) { /* Die Progressbar initialisieren, die den Gesamstatus anzeigt. */ _totalProgressBar = new ProgressBar(); _totalProgressBar.Maximum = ProgressBarMaxValue * links.Count(); _totalProgressBar.Top = TotalProgressBarTop; _totalProgressBar.Left = TotalProgressBarLeft; _totalProgressBar.Width = TotalProgressBarWidth; _totalProgressBar.Height = DLHeight; this.Controls.Add(_totalProgressBar); _totalProgressBar.Show(); _progressBarsLocks = new Dictionary<string, Object>(); _progressBars = new Dictionary<string, ProgressBar>(); _webClients = new Dictionary<string, WebClient>(); _labels = new Dictionary<string, Label>(); // Wird benutzt, um die Position der labels und progress bars zu setzen. int Top = DLStartTop; foreach (string link in links) { //Da ich hier der einfachheithalber mit locks gearbeitet habe, (das ist sicher nicht optimal, wie gesagt, //ich würde mir da mal ein Threadingbuch zu gute führen) verwende ich sicherheitshalber für jede Progressbar einen // eigenen Lock. _progressBarsLocks.Add(link, new Object()); //Progressbar für jede Datei die heruntergeladen wird initialisieren. ProgressBar pb = new ProgressBar(); pb.Top = Top; pb.Width = DLWidth; pb.Height = DLHeight; pb.Left = ProgressBar_Left; pb.Maximum = ProgressBarMaxValue; _progressBars.Add(link, pb); //Label für jede Datei die heruntergeladen wird initialisieren. Label label = new Label(); label.Text = Path.GetFileName(link); label.Left = DLLeft; label.Width = DLWidth; label.Height = DLHeight; label.Top = Top; label.ForeColor = Color.Red; _labels.Add(link, label); //Jede Datei braucht einen eigenen WebClienten. WebClient wc = new WebClient(); _webClients.Add(link, wc); this.Controls.Add(pb); this.Controls.Add(label); label.Show(); pb.Show(); Top += DLStep; //Handler für den Fall, dass eine Datei vollständig heruntergeladen wurde. //Falls dir die schreibweise nicht bekannt ist, mach dich mit Lambda expressions vertraut. wc.DownloadFileCompleted += new AsyncCompletedEventHandler( (sender, args) => { string link_to_file = args.UserState as string; Label progressBarLabel = _labels[link_to_file]; progressBarLabel.ForeColor = Color.Green; ProgressBar progressBar = _progressBars[link_to_file]; Object progressBarLock = _progressBarsLocks[link_to_file]; lock (progressBarLock){ progressBar.Value = progressBar.Maximum; } WebClient webClient = _webClients[link_to_file]; webClient.Dispose(); _webClients.Remove(link_to_file); lock (_totalProgressBarLock) { UpdateTotalProgressBar(); } } ); //Anpassen der Progressbars. wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler( (sender, args) => { string link_to_file = args.UserState as string; ProgressBar this_pb = _progressBars[link_to_file]; this_pb.Value = Convert.ToInt32((ProgressBarMaxValue / args.TotalBytesToReceive) * args.BytesReceived); lock (_totalProgressBarLock) { UpdateTotalProgressBar(); } } ); string fileName = Path.GetFileName(link); wc.DownloadFileAsync(new Uri(link), fileName, link); } } private void UpdateTotalProgressBar() { _totalProgressBar.Value = _progressBars.Sum((kvp) => kvp.Value.Value); } } |
Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von »Darkrel« (15.06.2011, 16:33)
Werbeanzeige