2009-04-25 27 views
1

Bis zu diesem Moment habe ich diese Methode verwendet, aufzurufen:Wie wird aufgerufen, wenn das Formular nicht aktiv ist?

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

Und hier ist das Problem:

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

ich einen Analysator ich schreibe, die Pakete zu analysieren. Ich kann das Formular nicht ständig fokussieren, weil ich Aktionen in der Anwendung machen muss. Ich schreibe diesen Analysator, um ein Paket zu bekommen, damit ich es analysieren kann.

Wenn ich die Anwendung, die ich analysieren möchte, zu berühren Formular.ActiveForm gibt null zurück.

Gibt es eine Möglichkeit, ich kann die Textbox aufrufen und festlegen, um Text hinzuzufügen, auch wenn das Formular nicht über alles ist?

Antwort

2

Ich denke, die Wurzel des Problems ist die enge Kopplung zwischen Ihrem Paketanalysator und der Hauptform. Ein Paketanalysator sollte nichts über das aktive Formular wissen müssen, oder sogar, dass es überhaupt ein Formular gibt. Es macht es schwer zu pflegen, weil es nur unter bestimmten Umständen funktioniert, die manchmal schon unwahr sind.

Sie könnten das Problem umkehren und ein Ereignis von der Klasse auslösen, die die Pakete analysiert. Dadurch erhalten Sie eine viel bessere Kapselung, da der Paketanalysator jetzt nichts über den Rest der Anwendung wissen muss. Sie können entweder eigene Ereignisargumente erstellen oder ein solches wie System.Diagnostics.DataReceivedEventArgs wiederverwenden. Dann kann Ihr Formular das DataReceived-Ereignis versenken und seinen eigenen AddText aufrufen, um zum Hauptthread zurückzukehren, und es funktioniert, ob das Formular sichtbar ist oder nicht.

Zumindest wird das funktionieren, aber es ist ein blockierender Aufruf, so dass der Paket-Analyzer-Thread gestoppt wird, bis das Formular das Ereignis vollständig verarbeitet und der Marshalled-Aufruf an den Haupt-Thread zurückgegeben wurde. Das wäre in Ordnung, wenn die Paketrate nicht sehr hoch ist, aber normalerweise möchten Sie nicht, dass ein Kommunikationsthread darauf wartet, dass der Hauptthread ein Textfeld aktualisiert. Ein anderer Ansatz wäre, den Text mit einem StringBuilder innerhalb des Paketanalysators zu protokollieren und ihn (den angesammelten Text, nicht den StringBuilder) über eine threadsichere öffentliche Eigenschaft verfügbar zu machen. Oder wenn Sie die einzelnen Nachrichten trennen müssen, können Sie sie beispielsweise zu einer Liste hinzufügen und die thread-safe -Eigenschaft ein Array von angesammelten Nachrichten zurückgeben. Dann könnte Ihr Formular den Analysator für neue geloggte Daten mit einem Timer mit der für Ihre Anwendung geeigneten Rate abfragen, und nur solange das Formular sichtbar ist. Es würde nicht ganz so schnell aktualisiert werden, aber die Auswirkungen auf den Analyzer-Thread wären fast null, und es sollte insgesamt schneller laufen, wenn es viele Nachrichten in den StringBuilder- oder List-in-between-Updates konsolidiert, anstatt mit jedem einzelnen Paket an die Text-Eigenschaft anzuknüpfen.

1

Sie könnten möglicherweise ein Unit of Work-Muster dafür mit dem OnActivation-Ereignis des Formulars verwenden.

Setzen Sie das 'wenn aktive Formular' Check-in Sie AddText-Methode. Wenn das Formular nicht aktiv ist, fügen Sie den Text für später in eine Liste ein.

Dann behandeln Sie das OnActivation-Ereignis des Formulars, und wenn die Liste Werte hat, drücken Sie sie zurück Thu AddText. Wenn dann das Formular aktiviert wird (dies passiert, wenn das Formular den Fokus erhält), füllt sich der Text.

Auch wenn der OnActivation-Teil nicht funktioniert, sollte dieses allgemeine Muster genügen.

1

Wenn das Problem, dass Sie nicht aufrufen können, dann Ihre Antwort wäre SynchronizationContext es ist immer auf dem Application.Run-Thread.So machen Sie folgendes:

In Form OnLoad speichern SynchronizationContext.Current zu statisches Feld überall. Danach können Sie einfach Post-oder Send-Methoden für die Synchronisierung oder asynchrone Aufrufe in GUI Thread verwenden.

Beschreibung hier: http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx

Nizza Artikel hier: http://www.codeproject.com/KB/cpp/SyncContextTutorial.aspx

1

Split das Problem in zwei Teile. Protokollieren Sie Ihren Text mit Trace.TraceInformation() und implementieren Sie einen TraceListener, der den Anzeigeaspekt verarbeitet.

Auf diese Weise können Sie Ihre Protokollausgabe einfach mit einem Eintrag in einer Konfigurationsdatei in eine Datei oder das Windows EventLog oder Ihre Benutzeroberfläche oder was auch immer umleiten. Sie müssen nicht nur einen auswählen. Sie können alle oben genannten tun, wenn es hilft.

Dies ist ein so alltägliches und häufiges Problem, dass das MSDN-Beispiel für die Implementierung eines TraceListener genau das ist, was Sie brauchen.

Verwandte Themen