2009-04-25 5 views
1

Jusqu'à ce moment, j'utilisé cette méthode pour invoquer:Comment appeler si le formulaire n'est pas actif?

public string AddText 
    { 
     set 
     { 
      if (listView1.InvokeRequired) 
      { 
       this.Invoke((MethodInvoker)delegate 
       { 
        Textbox.text += value + "\n"; 
       }); 
      } 
      else 
      { 
       Textbox.text += value + "\n"; 
      } 
     } 
    } 

Et voici le problème:

var form = Form.ActiveForm as Form1; 
    if (form != null) 
     form.AddText = "Test"; 

J'écris un analyseur qui analyse les paquets. Je ne peux pas mettre le formulaire au point tout le temps, parce que je dois faire des actions sur l'application. J'écris cet analyseur afin d'obtenir un paquet afin que je puisse l'analyser.

Si je touche l'application que je souhaite analyser Form.ActiveForm renvoie null.

Y at-il un moyen que je peux invoquer et définir la zone de texte pour ajouter du texte même si le formulaire n'est pas sur le dessus de tout?

Répondre

2

Je pense que la racine du problème est le couplage étroit entre votre analyseur de paquets et le formulaire principal. Un analyseur de paquets ne devrait pas avoir à connaître quoi que ce soit sur le formulaire actif, ou même qu'il y ait une forme quelconque. Cela rend les choses difficiles à maintenir parce que cela ne fonctionne que dans des circonstances très précises qui sont déjà fausses.

Vous pouvez inverser le problème et déclencher un événement de la classe qui analyse les paquets. Cela vous donne une bien meilleure encapsulation car l'analyseur de paquets n'a plus besoin de rien savoir sur le reste de l'application. Vous pouvez créer vos propres arguments d'événement ou en réutiliser un comme System.Diagnostics.DataReceivedEventArgs par exemple. Ensuite, votre formulaire peut faire couler l'événement DataReceived et appeler son propre AddText pour invoquer de nouveau le thread principal, et cela fonctionnera si le formulaire est visible ou non. Au moins, cela fonctionnera, mais c'est un appel bloquant, donc le thread d'analyse de paquets sera arrêté jusqu'à ce que le formulaire gère entièrement l'événement et l'appel de marshalled au thread principal a retourné. Ce serait bien si le taux de paket n'est pas très élevé mais habituellement vous ne voudriez pas arrêter un thread de communication pour attendre le thread principal pour mettre à jour une zone de texte. Une autre approche consisterait à consigner le texte à l'aide d'un StringBuilder dans l'analyseur de paquets et à l'exposer (le texte accumulé, pas StringBuilder) via une propriété publique thread-safe. Ou si vous avez besoin de séparer les messages inviduels, vous pouvez les ajouter à une liste par exemple, et avoir la propriété thread-safe retourne un tableau de messages accumulés. Ensuite, votre formulaire pourrait interroger l'analyseur pour de nouvelles données consignées à l'aide d'un minuteur, quel que soit le taux approprié pour votre application, et seulement lorsque le formulaire est visible. Il ne serait pas mis à jour aussi rapidement mais l'impact sur le thread d'analyseur serait presque nul et il devrait fonctionner plus rapidement s'il consolide plusieurs messages dans les mises à jour StringBuilder ou List plutôt que de concaténer sur la propriété Text avec chaque paquet.

1

Vous pouvez éventuellement utiliser un motif Unité de travail pour cela avec l'événement OnActivation du formulaire.

Mettez le formulaire 'if active forme' dans votre méthode AddText. Si le formulaire n'est pas actif, placez le texte dans une liste pour plus tard. Ensuite, manipulez l'événement OnActivation du formulaire et, si la liste contient des valeurs, repoussez-le par AddText. Ensuite, lorsque le formulaire est activé (cela se produit lorsque le formulaire obtient le focus) le texte se remplira.

Même si la partie OnActivation ne fonctionne pas, ce modèle général devrait faire l'affaire.

1

Si le problème que vous ne pouvez pas invoquer, alors votre réponse serait d'utiliser SynchronizationContext il est toujours disponible sur le thread Application.Run.Pour ce faire, procédez comme suit:

In Form OnLoad enregistrez SynchronizationContext.Current to static field anywhere. Ensuite, vous pouvez facilement utiliser les méthodes Post ou Send pour la synchronisation ou l'appel asynchrone dans le thread GUI.

Description de ici: http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx

Bel article ici: http://www.codeproject.com/KB/cpp/SyncContextTutorial.aspx

1

de Split le problème en deux parties. Consignez votre texte en utilisant Trace.TraceInformation() et implémentez un TraceListener qui gère l'aspect d'affichage. De cette façon, vous pouvez rediriger votre sortie de journal vers un fichier, ou le Windows EventLog, ou votre interface utilisateur, ou autre, simplement avec une entrée dans un fichier de configuration. Vous n'êtes pas obligé d'en choisir un seul. Vous pouvez faire tout ce qui précède si cela aide.

Il s'agit d'un problème banal et fréquent que l'exemple MSDN pour implémenter un TraceListener est exactement ce dont vous avez besoin.

Questions connexes