[C#] Hilfe bei Invoke

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von Berseker, 24. September 2012 .

Schlagworte:
Status des Themas:
Es sind keine weiteren Antworten möglich.
  1. 24. September 2012
    Hilfe bei Invoke

    Hallo RRler,

    ich brauch mal eure Hilfe.

    Also ich hab ein Programm geschrieben was abfragt ob der Editor läuft.
    Und wenn der Editor läuft dann soll ein labeltext in Editor geöffnet oder in Editor nicht geöffnet werden.
    Hatte den Code dafür so gemacht:

    Code:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Timers;
    using System.Windows.Forms;
    
    namespace Processopened
    {
     public partial class Form1 : Form
     {
     public Form1()
     {
     InitializeComponent();
     System.Timers.Timer aTimer = new System.Timers.Timer();
     aTimer.Elapsed += new ElapsedEventHandler(aTimer_Elapsed);
     aTimer.Interval = 1000;
     aTimer.Enabled = true;
     GC.KeepAlive(aTimer);
     }
    
     void aTimer_Elapsed(object sender, ElapsedEventArgs e)
     {
     if (IsProcessOpen("notepad") == true)
     {
     label1.Text = "Editor geöffnet";
     }
     else
     {
     label1.Text = "Editor nicht geöffnet";
     }
     }
    
     public bool IsProcessOpen(string name)
     {
     foreach (Process clsProcess in Process.GetProcesses())
     {
     if (clsProcess.ProcessName.Contains(name))
     {
     return true;
     }
     }
     return false;
     }
     private void Form1_Load(object sender, EventArgs e)
     {
     
     }
     }
    }
    
    dann bekomme ich aber folgende Fehlermeldung:
    bin jetzt nur soweit gekommen das ich da einen invoke brauche und weis aber nicht wie ich das schreiben muss.
    Hab es bis jetzt nur soweit:
    Code:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Timers;
    using System.Windows.Forms;
    
    namespace Processopened
    {
     public partial class Form1 : Form
     {
     public Form1()
     {
     InitializeComponent();
     System.Timers.Timer aTimer = new System.Timers.Timer();
     aTimer.Elapsed += new ElapsedEventHandler(aTimer_Elapsed);
     aTimer.Interval = 1000;
     aTimer.Enabled = true;
     GC.KeepAlive(aTimer);
     }
    
     void aTimer_Elapsed(object sender, ElapsedEventArgs e)
     {
     if (IsProcessOpen("notepad") == true)
     {
     if (label1.InvokeRequired)
     {
     
     }
     else
     {
     label1.Text = "Editor geöffnet";
     }
     }
     else
     {
     if (label1.InvokeRequired)
     {
    
     }
     else
     {
     label1.Text = "Editor nicht geöffnet";
     }
     }
     }
    
     public bool IsProcessOpen(string name)
     {
     foreach (Process clsProcess in Process.GetProcesses())
     {
     if (clsProcess.ProcessName.Contains(name))
     {
     return true;
     }
     }
     return false;
     }
     private void Form1_Load(object sender, EventArgs e)
     {
     
     }
     }
    }
    
    Weis grad wirklich nicht weiter..

    Danke schonmal im vorraus.

    MfG Berseker
     
  2. 24. September 2012
    Zuletzt bearbeitet: 24. September 2012
    AW: Hilfe bei Invoke

    Hallo.

    Das Problem ist folgendes:
    Der Timer läuft in einem eigenen Thread. Wenn das Event ausgelöst wird, dann würdest du aus einem Timer-Thread heraus die GUI ändern, dass ist aber nicht erlaubt.

    Die Lösung ist:
    du musst vom Timer-Thread aus den GUI-Thread "aufrufen" und der übernimmt dann die Änderungen an der GUI.

    Du kannst das auf 2 Arten lösen:
    Code:
     private delegate void LabelCallBack(string newText);
    
     private void setTextOnLabel(string newText)
     {
     if (label1.InvokeRequired)
     {
     LabelCallBack s = new LabelCallBack(setTextOnLabel);
     label1.Invoke(s, new object[] { newText });
     return;
     }
    
     label1.Text = newText;
     }
    
    void aTimer_Elapsed(object sender, ElapsedEventArgs e)
     {
     if (IsProcessOpen("notepad") == true)
     setTextOnLabel("Editor geöffnet");
     else
     setTextOnLabel("Editor nicht geöffnet");
     }
    
    Was passiert hier?
    Wenn die Methode aufgerufen wird, dann wird überprüft, ob wir uns in einem anderen Thread befinden, als der Thread, in dem der Label erzeugt wurde.
    (wird true sein => Timer-Thread ruft diese Methode auf -> ist nicht der GUI-Thread -> daher rein da und Delegate aufrufen).

    Wir erzeugen einen neuen Callback:
    LabelCallBack s = new LabelCallBack(setTextOnLabel);

    Wie du siehst, rufen wir die selbe Methode nochmals auf und übergeben erneut den Text, den wir als Parameter übergeben bekommen haben.

    Danach wird Invoke aufgerufen (wechseln in den Thread, in dem das Label erstellt wurde).

    Jetzt kommen wir wieder in diese Methode rein. InvokeRequired ist false, da wir jetzt im richtigen Thread sind (GUI) und der Text wird gesetzt.


    Die zweite Methode wäre mittels anonymen Delegate:
    Code:
    void aTimer_Elapsed(object sender, ElapsedEventArgs e)
     {
     if (IsProcessOpen("notepad") == true)
     {
     label1.Invoce(new Action(delegate()
     {
     label1.Text = "Editor geöffnet";
     }));
     }
     else
     {
     label1.Invoce(new Action(delegate()
     {
     label1.Text = "Editor nicht geöffnet";
     }));
     }
     }
    
    Effekt dürfte (müsste) der Selber sein.

    Wobei, wie du schon siehst, die 1. Variante die schönere ist. Diese kannst du auch sehr leicht und sehr schön wiederverwenden.

    Macht vor allem auch dann Sinn, wenn du den Text des Labels an mehreren Stellen ändern möchtest und auch mehrere Threads im Spiel sind. Somit kannst du sicher sein, dass diese Fehlermeldung nicht mehr kommt.

    Der Nachteil bei der 2. Variante ist auch der, dass immer Invoke aufgerufen wird (egal ob wir bereits im richtigen Thread sind oder nicht).

    Grüße,
    Rag
     
    1 Person gefällt das.
  3. 25. September 2012
    AW: Hilfe bei Invoke

    Ja danke habs mit Variante 1 gemacht,

    Funktioniert auch alles super.
    Danke für die schnelle Hilfe

    MfG Berseker
     
  4. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.