2009-12-10 4 views
1

J'ai un formulaire simple avec deux boutons (Start et Stop) et un DataGridView. J'essaie de remplir le DataGridView avec les résultats d'une requête WMI qui énumère les instances Win32_Process et place tous les noms de processus dans la seule colonne de DataGridView. Le code ressemble à ceci:L'application se bloque après le remplissage d'un DataGridView

using System; 
using System.Management; 
using System.Windows.Forms; 

namespace WindowsFormsApplication10 
{ 
    public partial class Form1 : Form 
    { 
     ManagementObjectSearcher Searcher = 
      new ManagementObjectSearcher(); 

     SelectQuery Query = new SelectQuery(); 

     ManagementOperationObserver Observer = 
      new ManagementOperationObserver(); 

     public Form1() 
     { 
      InitializeComponent(); 

      Observer.Completed += 
       new CompletedEventHandler(Observer_Completed); 
      Observer.ObjectReady += 
       new ObjectReadyEventHandler(Observer_ObjectReady); 
      Grid.ColumnCount = 1; 
      Grid.Columns[0].Name = "Name"; 
     } 

     private void Start_Click(object sender, EventArgs e) 
     { 
      Query.QueryString = "Select * From Win32_Process"; 
      Searcher.Query = Query; 

      Searcher.Get(Observer); 
     } 

     private void Observer_Completed 
      (object sender, CompletedEventArgs e) 
     { 
      Grid.Refresh(); 
     } 

     private void Observer_ObjectReady 
      (object sender, ObjectReadyEventArgs e) 
     { 
      string [] row = new string [] 
       {e.NewObject["Name"].ToString()}; 
      Grid.Rows.Add(row); 

      Grid.Refresh(); 
     } 

     private void stop_Click(object sender, EventArgs e) 
     { 
      Observer.Cancel(); 
     } 
    } 
} 

Quand je lance le code en utilisant l'option « Start Debugging », il fonctionne très bien et renseigne le DataGridView. Une chose étrange (au moins pour moi) j'ai remarqué est que dans la Observer_ObjectReady la ligne Grid.Refresh() n'est jamais atteinte. Lorsque je cours le code avec «Démarrer sans débogage» DataGridView est rempli mais le formulaire se bloque immédiatement après cela. Comment puis-je faire face à cela? (Désolé si ce n'est pas assez d'informations - Je suis prêt à fournir plus si nécessaire, mais, comme vous l'avez peut-être remarqué, je n'ai pas beaucoup d'expérience avec C# ou Visual Studio).

Répondre

0

Vous ne devez pas ajouter une ligne à votre GridView chaque fois que vous recevez une nouvelle entrée. Vous pouvez charger tous vos processus dans une collection et les lier à votre contrôle.

Je viens de découvrir ce lien et lire son code source peut vous aider à atteindre votre objectif: Manage Processes on Remote Machine

+0

Merci pour la réponse. Cette application utilise une énumération synchrone, et j'ai également réussi à le faire fonctionner de cette façon. Mon problème est que cela peut prendre beaucoup de temps lors de l'énumération des classes comme CIM_DataFile ou Win32_Directory. C'est pourquoi j'essaie d'utiliser l'énumération asynchrone (en utilisant l'événement ManagementOperationObserver.ObjectReady) mais je ne peux pas le faire fonctionner - l'application se fige. –

+0

devez-vous afficher toutes les données? pouvez-vous en quelque sorte paginer? –

+0

Parfois, j'ai besoin d'afficher toutes les données. L'énumération synchrone fonctionne bien mais pour Cim_DataFile l'énumération asynchrone serait le bon choix. J'ai été capable d'utiliser le même code asynchrone et d'envoyer les données à un RichTextBox, mais j'aimerais aussi pouvoir renseigner un DataGridView. Je suppose que cela a à voir avec un DataGridView, mais je suis perplexe parce que je ne reçois aucune exception, l'application se fige, alors que la même application fonctionne correctement lorsque je remplace le DataGridView par un RichTextBox et ajoute des lignes de texte de Observer_ObjectReady. –

0

Serait-ce une exception est lancée? Les Winforms ne s'arrêtent pas seulement lorsqu'une exception est levée, cette méthode est annulée et un événement que vous devez manipuler manuellement est levé. Vous devrez créer un gestionnaire d'exceptions pour les voir!

Application.ThreadException += 
    new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); 

Je pense que vous obtenez une exception de quelque chose - il se pourrait que ne pas appeler .Connect() sur le ManagementScope que vous aussi ne pas créer est de vous donner un problème ... la ce qui suit est une partie de ce que j'utilise et cela fonctionne pour moi en mode asynchrone. YMMV. En outre, comme Rubens l'a dit, le problème peut venir de la grille de données et de l'ajout d'une ligne à la fois. Avez-vous envisagé d'ajouter les éléments à une collection dans l'événement ObjectReady de l'observateur, puis de leur lier des données dans l'événement Completed de l'observateur? Une troisième possibilité pourrait être une combinaison des exceptions n'étant pas refaites et les événements de rappel étant faits à partir d'un thread non-UI - Tenter de mettre à jour les contrôles UI d'un autre thread est un grand non-non. Voir "How do I make event callbacks into my winforms thread safe?"

Espérons que quelque chose vous sera utile. :-)

Questions connexes