2010-09-24 3 views
4

J'essaie d'exécuter le code suivant. Le code essaie parallèlement de télécharger et de sauvegarder des images. Je passe une liste d'images à télécharger. J'ai écrit cela en C# 3.0 et l'ai compilé en utilisant .NET Framework 4 (VS.NET express edition). L'opération WaitAll entraîne une erreur NotSupportedException (WaitAlll pour plusieurs handles sur un thread STA n'est pas pris en charge) chaque fois que j'essaie d'exécuter mon programme. J'ai essayé d'enlever , mais cela n'a pas fait de différence.NotSupportedException sur WaitHandle.WaitAll

public static void SpawnThreads(List<string> imageList){ 
    imageList = new List<string>(imageList); 
    ManualResetEvent[] doneEvents = new ManualResetEvent[imageList.Count]; 
    PicDownloader[] picDownloaders = new PicDownloader[imageList.Count]; 
    ThreadPool.SetMaxThreads(MaxThreadCount, MaxThreadCount); 
    for (int i = 0; i < imageList.Count; i++) { 
     doneEvents[i] = new ManualResetEvent(false); 
     PicDownloader p = new PicDownloader(imageList[i], doneEvents[i]); 
     picDownloaders[i] = p; 
     ThreadPool.QueueUserWorkItem(p.DoAction); 
    } 
    // The following line is resulting in "NotSupportedException"  
    WaitHandle.WaitAll(doneEvents); 
    Console.WriteLine("All pics downloaded"); 
} 

Pouvez-vous s'il vous plaît me faire comprendre quel est le problème que je rencontre?

Merci

Répondre

5

Avez-vous marquer l'une des méthodes avec [STAThread] attribut?

+0

Merci Danny! Le thread d'application principal est en effet marqué comme [STAThread]. Je l'ai enlevé et fonctionne comme par magie. Pourquoi VS.NET par défaut toutes les méthodes d'entrée à [STAThread]? – rkg

+0

@Ravi: Je ne pense pas que cet attribut sera marqué '' par défaut '. Peut-être que c'était marqué par toi-même? –

+0

Je sais que c'est un peu vieux, mais dans VS2012 Express for Desktop - J'ai créé une toute nouvelle application à partir de zéro et en effet dans le fichier Program.cs, Main est décorée avec l'attribut STAThread. Je l'ai enlevé et maintenant ça marche pour moi. Merci les gars! – Losbear

0

Avez-vous essayé de placer l'état de l'appartement pour le fil?

thread.SetApartmentState (System.Threading.Apartmentstate.MTA); 
+0

Merci, mais je ne fais que créer un ThreadPool, pas des threads individuels! ThreadPool ne me permet pas de définir l'ApartmentState. – rkg

7

Je déconseille d'utiliser plusieurs instances WaitHandle pour attendre l'achèvement. Utilisez plutôt la classe CountdownEvent. Il en résulte un code plus élégant et évolutif. De plus, la méthode WaitHandle.WaitAll ne prend en charge que jusqu'à 64 poignées et ne peut pas être appelée sur un thread STA. En refactorisant votre code pour utiliser le modèle canonique, j'ai trouvé cela.

public static void SpawnThreads(List<string> imageList) 
{ 
    imageList = new List<string>(imageList); 
    var finished = new CountdownEvent(1); 
    var picDownloaders = new PicDownloader[imageList.Count]; 
    ThreadPool.SetMaxThreads(MaxThreadCount, MaxThreadCount); 
    for (int i = 0; i < imageList.Count; i++) 
    { 
    finished.AddCount();  
    PicDownloader p = new PicDownloader(imageList[i]); 
    picDownloaders[i] = p; 
    ThreadPool.QueueUserWorkItem(
     (state) => 
     { 
     try 
     { 
      p.DoAction 
     } 
     finally 
     { 
      finished.Signal(); 
     } 
     }); 
    } 
    finished.Signal(); 
    finished.Wait(); 
    Console.WriteLine("All pics downloaded"); 
} 
+0

Merci Brian. Je vais essayer ça. – rkg

Questions connexes