2009-11-24 12 views
1

J'écris une application en C#, et je crée plusieurs threads BackgroundWorker pour récupérer des informations à partir de pages Web. Bien qu'ils soient BackgroundWorkers, mon formulaire GUI ne répond plus. Lorsque je débogue, je fais une pause lorsque le programme ne répond plus, et je peux voir que je suis dans le fil principal, et je suis suspendu sur la méthode de récupération de page Web. Cependant, cette méthode n'est appelée qu'à partir de nouveaux threads, donc je ne peux pas comprendre pourquoi je serais là dans le thread principal.Threading requêtes Web traitées dans Main?

Est-ce que cela a un sens? Que puis-je faire pour m'assurer que les requêtes Web ne sont traitées que dans leurs threads respectifs?

EDIT: un code et une explication

Je traite une grande liste d'adresses. Chaque thread traitera une ou plusieurs adresses. Je peux choisir le nombre de threads que je veux créer (je le garde modeste :))

//in “Controller” class 
public void process() 
{ 
for (int i = 1; i <= addressList.Count && i<= numthreads; i++) 
      { 
       BackgroundWorker bw = new BackgroundWorker(); 
       bw.DoWork += doWork; 
       bw.RunWorkerAsync((object)i); 
      } 
} 

public void doWork(object sender, DoWorkEventArgs e) 
{ 
    //create an object that has the web fetching method, call it WorkObject 
    //WorkObject keeps a reference to Controller. 
    //When it is done getting information, it will send it to Controller to print 
    //generate a smaller list of addresses to work on, using e.Argument (should be 'i' from the above 'for' loop) 
    WorkObject.workingMethod() 
} 

Quand est créé du repère objet, il utilise « i » de savoir quel numéro fil il est. Il l'utilisera pour obtenir une liste d'adresses Web pour obtenir des informations (à partir d'une plus grande liste d'adresses qui est partagée par le Formulaire principal, le Contrôleur et chacun des WorkObjects - chaque thread traitera une plus petite liste d'adresses). Comme il itère sur la liste, il appellera la méthode "getWebInfo".

//in “WorkObject” class 
public static WebRequest request; 

public void workingMethod() 
{ 
    //iterate over the small list of addresses. For each one, 
     getWebInfo(address) 
     //process the info a bit...then 
     myController.print() 

//note that this isn’t a simple “for” loop, it involves event handlers and threading 
//Timers to make sure one is done before going on to the next 
} 

public string getWebInfo (string address) 
{ 
    request = WebRequest.Create(address); 
       WebResponse response = request.GetResponse(); 
       StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8); 
       string content = reader.ReadToEnd(); 
       return content; 
} 
+2

Pouvez-vous poster du code? le code initiant les threads et les demandes – mfeingold

+0

OK. J'espère que c'est assez/pas trop d'infos. – Matt

Répondre

0

Vous devriez effectuer tout le travail en ligne dans l'événement DoWork de votre BackgroundWorker, n'est-ce pas?

Un code tronqué peut nous aider à comprendre ce qui se passe.

+0

Très bien, édité le code post-ajouté. J'espère que c'est assez d'infos – Matt

0

Dans une situation similaire, j'ai trouvé que j'avais un meilleur contrôle en créant mes propres threads (sans BackgroundWorker et sans ThreadPool) et en limitant le nombre de connexions actives. Ecrivez les adresses IP dans une file d'attente, puis sélectionnez-les, en les passant à une classe d'assistance où vous appelez sa méthode DoSomething sur un nouveau thread. Throttle en incrémentant un compteur lorsque vous lancez un thread et le décrémenter lorsque le thread se termine. Vous pouvez utiliser les routines de rappel de votre classe d'assistance pour signaler à votre thread d'interface utilisateur de mettre à jour l'interface ou indiquer qu'un thread est terminé. Utilisez votre interface utilisateur pour modifier la limite d'accélération et observez le Gestionnaire des tâches pour voir l'effet sur la mémoire et l'utilisation de l'unité centrale. Vous pouvez ajouter un paramètre maxconnection dans votre app.config pour obtenir plus de connexions simultanées.

+0

A l'origine, je créais mes propres threads, mais cela provoquait le blocage de l'interface utilisateur, j'ai donc décidé d'essayer BackgroundWorkers. Toujours avoir le même problème. L'utilisation du processeur et l'utilisation de la mémoire sont généralement assez faibles - sauf quand je lui dis de créer un tas de threads en même temps, mais il s'éteint une fois qu'ils sont en marche. – Matt