2010-01-20 13 views
1

J'essaie de créer un outil réseau simple pour exécuter une commande ping sur toutes les adresses IP possibles sur votre sous-réseau local et fournir une liste de ces adresses dans un DataGridView. Je suis nouveau à avoir à considérer threading qui est une bonne chose à rencontrer en tant que programmeur en herbe. Désolé, mais vous allez probablement devoir m'expliquer, mais dans mon esprit cela devrait fonctionner. Avant d'essayer de le placer dans un fil d'arrière-plan, l'application se bloquait et me donnait un "Ne répondant pas".Problèmes de threading en utilisant Ping pour mapper les adresses IP actives - C#

merci d'avance.

 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     count = 0; 
     for (int j = 1; j < 255; j++) 
      for (int i = 1; i < 255; i++) 
      { 
       Ping ping = new Ping(); 
       PingReply pingreply = ping.Send(IPAddress.Parse(locip[0] + "." + locip[1] + "." + j + "." + i)); 

       if (pingreply.Status == IPStatus.Success) 
       { 
        status = "o"; 
        repAddress = pingreply.Address.ToString(); ; 
        repRoundtrip = pingreply.RoundtripTime.ToString(); 
        repTTL = pingreply.Options.Ttl.ToString(); 
        repBuffer = pingreply.Buffer.Length.ToString(); 

        string[] lineBuffer = { status, repAddress, repRoundtrip, repTTL, repBuffer }; 
        ipList.Rows.Add(lineBuffer); 
        count += 1; 
        progressBar.Value += 1; 
       } 

      } 


    } 
+0

Donc, cela est ou n'est pas dans un BackgroundWorker? Pouvez-vous nous montrer votre code d'installation de thread? – cmw

+0

Dans la vue de conception, j'ai ajouté un objet BackgroundWorker appelé backgroundWorker1 et sur l'événement click du bouton 1, j'ai appelé backgroundWorker1.RunWorkerAsync(); Mais encore une fois, je crois que le problème réside dans la routine ping et les boucles. Avant même que j'aie ajouté le BackgroundWorker il se bloquerait et gèlerait ("ne répondant pas") quand ce code exact était dans un événement de clic. P.S. Travailler avec Visual Studio 2008 – user48202

+1

Euh, vous faites 65536 pings. Beaucoup d'entre eux sont tenus de ne pas répondre. Vous devez le localiser dans le sous-réseau final. C'est beaucoup trop à gérer de manière significative. –

Répondre

1

Une partie du problème est que vous accédez directement un élément d'interface de votre fil d'arrière-plan. Le champ progressBar est probablement un contrôle de barre de progression de l'interface utilisateur et ne peut être accessible en toute sécurité qu'à partir du thread d'interface utilisateur. Vous devez utiliser un appel à .Invoke pour définir cette valeur à partir du thread d'interface utilisateur.

progressBar.Invoke(new MethodInvoker(UpdateProgressBarbyOne)); 
... 

private void UpdateProgressBarByOne() { 
    progressBar.Value += 1; 
} 
+0

merci pour le conseil sur la barre de progression, mais pouvez-vous entrer dans un peu plus de détails sur la façon d'accomplir cela? (quoi?). Invoquez – user48202

+0

@jon, chose certaine. Mise à jour ma réponse – JaredPar

2

Vous ne pouvez pas accéder directement au progressBar1 (ou tout autre élément d'interface utilisateur) de l'événement backgroundWorker1 "DoWork", vous devez utiliser la méthode backgroundWorker1.ProgressChanged et gérer l'événement ProgressChanged:

// instead of progressBar.Value += 1 
// use the following 

const int total = 254 * 254; 
backgroundWorker1.ReportProgress(count/total); 

WorkerReportsProgress devrait être affecté à vrai et l'événement de ProgressChanged la méthode suivante

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    // assuming the Minimum = 0 and Maximum = 100 on progressBar 
    progressBar.Value = e.ProgressPercentage; 
} 
0

Ah j'adore enfiler. Il fait des programmes beaucoup plus intéressant ...

Comme je l'ai commencé à apprendre comment faire des applications sensibles, je suis tombé sur la fonction: Application.DoEvents()

(http://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents.aspx)

Ce que cela fait est provoque votre formulaire à traiter certains des événements de fenêtre qu'il reçoit. Je pense que votre code pourrait changer d'inclure un appel après chaque requête ping ...

-à-dire dans le gestionnaire d'événement on click

count = 0; 
     for (int j = 1; j < 255; j++) 
      for (int i = 1; i < 255; i++) 
      { 
       Ping ping = new Ping(); 
       PingReply pingreply = ping.Send(IPAddress.Parse(locip[0] + "." + locip[1] + "." + j + "." + i)); 

       if (pingreply.Status == IPStatus.Success) 
       { 
        status = "o"; 
        repAddress = pingreply.Address.ToString(); ; 
        repRoundtrip = pingreply.RoundtripTime.ToString(); 
        repTTL = pingreply.Options.Ttl.ToString(); 
        repBuffer = pingreply.Buffer.Length.ToString(); 

        string[] lineBuffer = { status, repAddress, repRoundtrip, repTTL, repBuffer }; 
        ipList.Rows.Add(lineBuffer); 
        count += 1; 
        progressBar.Value += 1; 
       } 
       Application.DoEvents(); //but not too often. 
      } 

Maintenant, c'était dans les jours nets avant de points et il a survécu jusqu'à ce maintenant cependant, ce n'est pas quelque chose que vous devriez prendre à la légère. Si vous cliquez sur un autre bouton du formulaire, il démarrera un autre thread qui tentera de s'exécuter et, si vous ne faites pas attention, provoquerez des exceptions de thread sur votre formulaire. Certains développeurs vous diront de ne pas l'utiliser mais depuis que vous avez démarré, je dirais qu'il faut essayer :)

Je n'utilise peut-être pas cette méthode en fonction de l'application. Au contraire, ce que je ferais en réalité, c'est de créer plusieurs «trains» de traitement; un pour chaque cpu core que le système avait. J'ajouterais les ips à balayer à un objet de file d'attente et ensuite je commencerais 2 à 4 instances de threads (http://msdn.microsoft.com/en-us/library/system.threading.thread.aspx) dont chacun prendrait un élément de la file à son tour, traiterait l'information (c.-à-d. et mettre le résultat sur une autre file d'attente; et file d'attente de sortie. Chaque fois qu'un train finirait un article pour le travail, il déclencherait un événement à l'autre extrémité duquel il y aurait un gestionnaire dans le formulaire. En utilisant Invoke pour faire des appels threads sûrs (http://msdn.microsoft.com/en-us/library/ms171728.aspx) sur mon formulaire je mettrais à jour les informations de l'interface utilisateur en conséquence. Thread est amusant mec :) au fil du temps, vous pouvez trouver que vous pouvez utiliser MSMQ pour faire un système qui utilise les multicœurs d'autres ordinateurs pour faire des travaux tels que le traitement d'image (ou quelque chose avec pa .......;)