2010-01-11 7 views
6

J'utilise le code ci-dessous pour télécharger plusieurs pièces jointes à partir d'un serveur TFS:WebClient.DownloadFileAsync - Télécharger des fichiers un à la fois

foreach (Attachment a in wi.Attachments) 
{  
    WebClient wc = new WebClient(); 
    wc.Credentials = (ICredentials)netCred; 
    wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted); 
    wc.DownloadFileAsync(a.Uri, "C:\\" + a.Name); 
} 

Je voudrais télécharger plusieurs fichiers à l'aide DownloadFileAsync, mais je les veux être téléchargé un par un.

On peut demander "Pourquoi n'utilisez-vous pas simplement la méthode synchrone DownloadFile?" C'est parce que:

  1. Je veux utiliser les événements fournis par DownloadFileAsync.
  2. Je ne souhaite pas créer plusieurs instances de Webclient pour éviter d'inonder le serveur.

C'est la solution que je pensais:

foreach (Attachment a in wi.Attachments) 
{   
    WebClient wc = new WebClient(); 
    wc.Credentials = (ICredentials)netCred; 
    wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted); 
    wc.DownloadFileAsync(a.Uri, "C:\\" + a.Name); 
    while (wc.IsBusy) 
    { 
     System.Threading.Thread.Sleep(1000); 
    } 
} 

Cependant, il y a quelques problèmes avec cette approche:

  1. Le Thread.Sleep() est mon verrouillage Forme. Je dois encore créer mon propre thread ou utiliser BackgroundWorker. (Je voudrais éviter cela autant que possible)
  2. L'événement DownloadFileCompleted est déclenché après TOUS les fichiers ont été téléchargés. Je ne sais pas si cela est un effet secondaire de l'utilisation de System.Threading.Thread.Sleep (1000);

Existe-t-il une meilleure approche pour télécharger des fichiers un à la fois en utilisant WebClient.DownloadFileAsync?

Merci!

+2

btw, vous pouvez utiliser 'System.IO.Path.Combinte (" C: ", a.Name"); ' – abatishchev

+0

J'essaie mais certaines réponses ne sont tout simplement pas acceptables. – Ian

+0

Vous pouvez résoudre le problème de blocage des threads en procédant comme suit: 'while (wc.IsBusy) {}'. De cette façon, tant que 'wc.IsBusy' est' true', l'exécution sera "bloquée" dans les accolades vides "ne rien faire". –

Répondre

8

Pour simplifier la tâche, vous pouvez créer une liste des pièces jointes départage:

list = new List<Attachment>(wi.Attachments); 

liste est champ privé avec le type Liste < Pièce jointe >. Après cela, vous devez configurer WebClient et commencer le téléchargement du premier fichier:

if (list.Count > 0) { 
    WebClient wc = new WebClient(); 
    wc.Credentials = (ICredentials)netCred; 
    wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted); 
    wc.DownloadFileAsync(list[0].Uri, @"C:\" + list[0].Name); 
} 

Votre gestionnaire de DownloadFileComplete doit vérifier si pas tous les fichiers déjà téléchargés et appelez DownloadFileAsync nouveau:

void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { 
    // ... do something useful 
    list.RemoveAt(0); 
    if (list.Count > 0) 
     wc.DownloadFileAsync(list[0].Uri, @"C:\" + list[0].Name); 
} 

Ce code n'est pas optimisé solution . C'est juste une idée.

0

Je pense qu'il faut utiliser la file d'attente

+0

Je suis d'accord RE en utilisant la file d'attente, mais comme Harshal a dit que vous devriez expliquer plus loin ce que vous dites. –

1

Au risque de paraître comme un idiot, cela a fonctionné pour moi:

Console.WriteLine("Downloading..."); 
client.DownloadFileAsync(new Uri(file.Value), filePath); 
while (client.IsBusy) 
{ 
    // run some stuff like checking download progress etc 
} 
Console.WriteLine("Done. {0}", filePath); 

client est une instance d'un objet WebClient.

+0

Fonctionne plutôt bien (Y) –

Questions connexes