Laden...

Event wird zu häufig geworden und überschreibt String - Wie kann man das umgehen?

Erstellt von rasemaier vor 7 Jahren Letzter Beitrag vor 7 Jahren 1.655 Views
R
rasemaier Themenstarter:in
24 Beiträge seit 2015
vor 7 Jahren
Event wird zu häufig geworden und überschreibt String - Wie kann man das umgehen?

Guten Morgen

Ich habe ein Problem mit einem Event den ich erstellt habe.
Er funktioniert zwar, aber wenn zu viele Eregnisse hintereinander ablaufen, wird er überschrieben bzw der vorherige Text wird nicht ausgegeben sonder der nächste 2 mal.

in meiner Dll gebe ich mit der Funktion ActionString Ereignisse aus.

//Event
        public event EventHandler<HandleActionString> EventActionStringReceived;

        // Methode, die das Event auslöst
        protected void ActionString(string message)
        {

            EventActionStringReceived?.Invoke(this, new HandleActionString(message));
            
        }

in einer seperaten Klasse:


    public class HandleActionString : EventArgs
    {
        public string ActionString { get; private set; }

        public HandleActionString(string actionstring)
        {
            ActionString = actionstring;
        }
    }

und so rufe ich den Event in meinem Programm auf:



string actionString = "";
klasse.EventActionStringReceived += Ethernet_ActionString;



 private void Ethernet_ActionString(object sender, HandleActionString e)
        {
            actionString = e.ActionString;

            this.BeginInvoke(new EventHandler(AusgabeActionString));
        }


1.040 Beiträge seit 2007
vor 7 Jahren
string actionString = "";  
  
 private void Ethernet_ActionString(object sender, HandleActionString e)  
        {  
            actionString = e.ActionString;  
  
            this.BeginInvoke(new EventHandler(AusgabeActionString));  
        }  
  
  

Was macht denn die Funktion AusgabeActionString?
So wie es aussieht, ist der actionString eine Klassenvariable, die bei jedem Event neu gesetzt wird. Das erklärt den von dir erwähnten Effekt.
Du solltest also den ActionString aus den EventArgs direkt in die Funktion AusgabeActionString geben.

3.003 Beiträge seit 2006
vor 7 Jahren

Ergänzend zu dem, was p!lle schrieb:

  • Event wird zum ersten Mal ausgelöst
  • in der Eventbehandlung wird die Instanzvariable "actionString" gefüllt und eine asynchron ablaufende Methode gestartet, die wiederum (offenbar) auf die Instanzvariable zugreift
  • während diese Methode läuft, wird das Event zum zweiten Mal ausgelöst
  • die Instanzvariable wird mit dem Wert der zweiten Auslösung überschrieben und die asynchrone Methode ein zweites Mal gestartet
  • jetzt läuft die asynchrone Methode also zweimal, während die Instanzvariable den Wert der zweiten Eventauslösung hat
  • peng

Entweder du überlegst dir eine bessere Weise, die Argumente der Ereignisse zu speichern, als immer wieder eine Instanzvariable zu überschreiben (da gibt es fertige Lösungen), oder du übergibst der asynchronen Methode direkt das Argument, wie p!lle vorgeschlagen hat. Kommt drauf an, was du vor hast.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

R
rasemaier Themenstarter:in
24 Beiträge seit 2015
vor 7 Jahren

Danke für deine Antwort

AusgabeActionString schreibt den string in eine textBox

Die Variable hab ich definiert, da ich per BeginInvoke nichts übergeben kann.

Gruss

3.003 Beiträge seit 2006
vor 7 Jahren

Kannst du erläutern, wieso du glaubst, BeginInvoke nutzen zu müssen?

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

R
rasemaier Themenstarter:in
24 Beiträge seit 2015
vor 7 Jahren

Der Event wird von verschiedenen Threads verwendet.
Wenn ich das nicht mit BeginInvoke mache bekomme ich den Fehler

Fehlermeldung:
Ein Ausnahmefehler des Typs "System.InvalidOperationException" ist in System.Windows.Forms.dll aufgetreten.

Zusätzliche Informationen: Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement textBoxMeldung3 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.

R
rasemaier Themenstarter:in
24 Beiträge seit 2015
vor 7 Jahren

So habs gelöst, danke das ihr mich auf den Fehler aufmerksam gemacht habt! super Forum hier 😄

        private object m_sync = new object();

        public delegate void Testdelegate(string msg);

        private void Ausgabedelegate(string msg)
        {
            
                textBoxMeldung3.Text += msg + "\n";
            
        }
        private void Ethernet_ActionString(object sender, HandleActionString e)
        {
            lock (m_sync)
            {
                textBoxMeldung3.Invoke(new Testdelegate(Ausgabedelegate), e.ActionString);
            }
        }
3.003 Beiträge seit 2006
vor 7 Jahren

Das ist zwar eine Antwort, sie passt nur leider nicht zur Frage 😉

Es existieren BeginInvoke() und Invoke(), und die Frage war, wieso du Ersteres nutzt. Davon abgesehen würde man einfach so etwas hier machen:


if (InvokeRequired)
    BeginInvoke(new MethodInvoker(() => myTextBox.Text = e.ActionString));
else
    myTextBox.Text = e.ActionString;

LaTino
EDIT: Das Locking ist unnötig. Invoke ist threadsafe.
EDIT2: zur Lektüre (ist wirklich nur ganz kurz) empfohlen: How to: Make Thread-Safe Calls to Windows Forms Controls

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)