myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Basistechnologien und allgemeine .NET-Klassen » Wie kann ich auf das abonnieren eines Events reagieren?
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Wie kann ich auf das abonnieren eines Events reagieren?

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
STF-DIR STF-DIR ist männlich
myCSharp.de-Mitglied

Dabei seit: 11.09.2006
Beiträge: 353
Entwicklungsumgebung: VS2008


STF-DIR ist offline

Wie kann ich auf das abonnieren eines Events reagieren?

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

ich habe eine Klasse, die ein Event zur Verfügung stellt.
Beim instanzieren der klasse wird in deren Konstruktor eine Methode aufgerufen,welche prüft ob eine Verbindung zu einem Dienst verfügbar ist oder nicht.
falls nicht wird ein Timer gestartet, der dann immer wieder prüft ob die Verbindung hergestellt werden kann oder nicht.
Dabei wird dann das event gefeuert und in meiner Form wird dann ein Panel rot oder grün.

Soweit so gut, wenn die Verbindung beim starten ( instanzieren der Klasse ) noch nicht hergestellt werden kann funktioniert das ganze super.
Allerdings wenn die Verbindung beim instanzieren hergestellt werden kann wird ja der Timer gestoppt, und somit das event nicht gefeuert. ( mein statuspanel nicht aktualisiert )
Der Timer läuft erst wieder an, wenn eine Methode in der klasse aufgerufen wird und keine Verbindung mehr besteht.

In meiner Form instanziere ich also die klasse und rufe den Konstruktor auf, und DANACH abonniere ich aber erst das event.
Also wird das Statuspanel beim instanzieren der Klasse nicht aktualisiert, wenn schon eine Verbindung hergestellt wurde.

Mir fehlt jetzt ein bisschen der Ansatz wie man das lösen könnte, da der Timer ja auch nicht immer laufen soll.

Habt ihr eine Idee wie man das lösen kann ?

Matthias
23.01.2019 15:03 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 12.948
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von STF-DIR:
Beim instanzieren der klasse wird in deren Konstruktor eine Methode aufgerufen,welche prüft ob eine Verbindung zu einem Dienst verfügbar ist oder nicht.

Das sollte man tunlichst nicht tun.

Eine Verbindung ist *fast* immer eine asynchrone Kommunikation.
Ein Konstruktor ist aber nicht asynchron, kann er auch nie sein.

Daher gehört sowas - insbesondere auch aufgrund SoC und der Testbarkeit - niemals in einen Konstruktor sondern in eine Methode.

Insgesamt ist das auch eher ein Problem des Code Designs, nicht der Ursache eines Events.
Ergo:
- Konstruktor macht nur das, wofür er da ist: eine Instanz erstellen
- Dann abonnierst Du die Events
- Dann prüfst Du die Verbindung

Natürlich sollte die Klasse auch einen State halten.
Insgesamt ist das alles in wenigen Zeilen zB mit Reactive Extensions umsetzbar.

Könnte zB so aussehen (hier im Editor geschrieben, daher keine Garantie).

C#-Code:
public class HttpEndpointChecker : IDisposable
{
    public string Uri {get;}
    public TimeSpan Interval {get;}

    public bool IsRunning {get { return !(_trigger is null); } }
    public bool IsAvailable{get;set;}

    private IDisposable _trigger;

    public HttpEndpointChecker(string uri, TimeSpan interval)
    {
        Uri = uri;
        Interval = interval;
    }

    public bool Start()
    {
       if(IsRunning) return false;

        _trigger = Observable
            .Interval(Interval)
            .Select(async _ => await VerifyAsync())
            .Subscribe();

        return true;
    }
    public bool Stop()
    {
       if(!IsRunning) return false;

        _trigger.Dispose();
        _trigger = null;

        return true;
    }

    private async Task VerifyAsync()
    {
        var httpRequest = await ...;
        IsAvailable = httpRequest.Succeeded;
    }

    public void Dispose()
    {
        if(!(_trigger is null))
        {
            _trigger.Dispose();
            _trigger = null;
        }
    }
}
23.01.2019 15:23 Beiträge des Benutzers | zu Buddylist hinzufügen
STF-DIR STF-DIR ist männlich
myCSharp.de-Mitglied

Dabei seit: 11.09.2006
Beiträge: 353
Entwicklungsumgebung: VS2008

Themenstarter Thema begonnen von STF-DIR

STF-DIR ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

danke für die Antwort, dann mache ich das so.

Ich habe von Euch schon öfter den Hinweis bekommen das mein Code Designs nicht besonders ist.
Da ich mir das bisschen Wissen selber beigebracht habe und auch nur für mich benutze, habe ich mich darum noch nie so richtig gekümmert.

Habt ihr da einen guten Quellenhinweis für gutes Code Design?

Matthias
23.01.2019 18:19 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 12.948
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Code Design und Architektur ist eines der wenigen Dinge, bei denen ich auf Bücher verweisen würde.
Allgemein helfen da als Basis durchaus so Bücher wie Gang of Four, Clean Code....
Erich Gamma, Martin Fowler, Kent Beck oder zB auch Robert C Martin kann man da durchaus als Orientierung nehmen.

Ansonsten halt viel Erfahrung etc.
Wenn man die Chance hat an Code Reviews teilnehmen zu können: das hilft enorm.

Immo Landwerth überträgt regelmäßig Code Reviews zu .NET live aus den Microsoft Büros.
23.01.2019 21:43 Beiträge des Benutzers | zu Buddylist hinzufügen
STF-DIR STF-DIR ist männlich
myCSharp.de-Mitglied

Dabei seit: 11.09.2006
Beiträge: 353
Entwicklungsumgebung: VS2008

Themenstarter Thema begonnen von STF-DIR

STF-DIR ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

danke, ich werd mir das mal zu gemüte führen.

Ich habe mich an deinem Code versucht, bin aber leider nicht ganz weiter gekommen.
Ich hab mal ein neues Project erstellt um das mal zu testen.
Allerdings funktioniert das ganze noch nicht so ganz.
Ich versteh nicht, wie ich die Änderung im connection status abfangen kann.
Leider hab ich mit Tasks und await/async noch keine erfahrungen, aber die kann man ja auch nur so sammeln.

Ich hab das mal absichtlich alles in eine Datei geschrieben, der Einfachheit halber.

C#-Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using FSUIPC;

namespace TestObserver
{
    public class FsuipcInfo
    {
        public FsuipcInfo()
        {
        }

        public async Task<bool> GetFsuipcState()
        {
            bool running = false;
            try
            {
                /// Hier wird geprüft ob eine Abfrage erfolgreich ist Wenn nicht
                /// bleibt running = false
                FSUIPCConnection.Process();
                running = true;
            }
            catch (Exception eex)
            {


            }
            return await Task.FromResult<bool>(running);
        }
    }



    public class FsuipcHandler
    {
        public delegate void FsuipcState();
        public event FsuipcState OnFsuipcStateChanged;

        public async Task<bool> AccessFsuipcAsync()
        {
            FsuipcInfo fi = new FsuipcInfo();
            Task<bool> fiTast = fi.GetFsuipcState();
            bool running = await fiTast;

            if (OnFsuipcStateChanged != null)
            {
                OnFsuipcStateChanged();
            }

            return running;
        }

    }
    public partial class Form1 : Form
    {
        FsuipcHandler fh;
        public Form1()
        {
            InitializeComponent();
            fh = new FsuipcHandler();
            fh.OnFsuipcStateChanged += Fh_OnFsuipcStateChanged;
        }

        private void Fh_OnFsuipcStateChanged()
        {
            MessageBox.Show("OnFsuipcStateChanged");
        }

        private async void getFsuipcState()
        {
            await fh.AccessFsuipcAsync();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            getFsuipcState();
        }
    }

}

Nun hab ich zwar das event abonniert, aber wenn die Verbindung nicht zur verfügung steht dann passiert nix :-(

Vielleicht kannst du da noch mal kurz drüber schauen.
Da scheint irgendwie dieser Teil

C#-Code:
    private async Task VerifyAsync()
    {
        var httpRequest = await ...;
        IsAvailable = httpRequest.Succeeded;
    }

zu fehlen, aber ich weiß leider nicht wie ich das implementieren kann?

Matthias
23.01.2019 22:47 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 12.948
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Dein Code hat ja insgesamt fast nichts mit meinem am Hut ;-)

Wo wird denn bei Dir geprüft?
23.01.2019 23:03 Beiträge des Benutzers | zu Buddylist hinzufügen
STF-DIR STF-DIR ist männlich
myCSharp.de-Mitglied

Dabei seit: 11.09.2006
Beiträge: 353
Entwicklungsumgebung: VS2008

Themenstarter Thema begonnen von STF-DIR

STF-DIR ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

ja sorry, ich muss es ja auf die FSUIPC ummünzen.
Wie gesagt, ich hab nich nie was mit Task/async/await gemacht, aber jeder hat ja mal angefangen :-)
Geprüft wird hier:

C#-Code:
        public async Task<bool> GetFsuipcState()
        {
            bool running = false;
            try
            {
                /// Hier wird geprüft ob eine Abfrage erfolgreich ist Wenn nicht
                /// bleibt running = false
                FSUIPCConnection.Process();
                running = true;
            }
            catch (Exception eex)
            {


            }
            return await Task.FromResult<bool>(running);
        }

Wenn FSUIPC.Process() funktioniert, dann wird running = true, ansonsten bleibt es false.
In dieser FSUIPC geschichte gibt es keine andere möglichkeit zu prüfen, ob eine Verbindung hergestellt werden kann oder nicht.

Matthias
23.01.2019 23:13 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 12.948
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Vermutlich sollte es eher in folgende Richtung gehen:

C#-Code:
    public class FsuipcInfoStateChangedArgs : EventArgs
    {
        public bool IsAvailable {get;}
        public FsuipcInfoStateChangedArgs( bool isAvailable )
        {
            IsAvailable = isAvailable;
        }
    }

    public class FsuipcInfo
    {
        public FsuipcInfo(TimeSpan interval)
        {
           Interval = interval;
        }


        public TimeSpan Interval {get;}
        private IDisposable _trigger;

        public bool IsRunning {get { return !(_trigger is null); } }
        public bool IsAvailable{get;}

        public delegate void FsuipcInfoStateChangeHandler( object sender, FsuipcInfoStateChangedArgs e );
        public event FsuipcInfoStateChangeHandler OnStageChanged;

        public bool Start()
        {
            if(IsRunning) return false;

            _trigger = Observable
                .Interval(Interval)
                .Select(isAvailable => Observable.FromAsync(async () => await IsAvailableFsuipc())
                .Subscribe(isAvailable => SetState(isAvailable));

            return true;
        }

        public bool Stop()
        {
            if(!IsRunning) return false;

            _trigger.Dispose();
            _trigger = null;

            return true;
        }

        private void SetState(bool currentState)
        {
            if(currentState != IsAvailable)
            {
               IsAvailable = currentState;
               FireStateChange(IsAvailable);
            }
        }

        private void FireStateChange(bool isAvailable)
        {
            if ( OnStageChanged != null )
            {
                OnStageChanged(this, new FsuipcInfoStateChangedArgs(isAvailable))
            }
        }

        public async Task<bool> IsAvailableFsuipc()
        {
            return await Task.Run( () =>
            {
                try
                {
                    /// Hier wird geprüft ob eine Abfrage erfolgreich ist Wenn nicht
                    /// bleibt running = false
                    FSUIPCConnection.Process();
                    return true;
                }
                catch (Exception ee)
                {
                    return false;
                }
            }).ConfigureAwait(false);
        }
    }

In diesem Falle kann man auch auf das async verzichten, wenn die Komponente async nicht unterstützt - bleibt halt Deine UI hängen und Du musst es wieder in nen Thread auslagern.
Daher hier die bessere Variante mit einem Wrap via Task.Run().

Ansonsten: mach paar Tutorials durch.
Tasks und Threads muss man verstehen.
23.01.2019 23:24 Beiträge des Benutzers | zu Buddylist hinzufügen
STF-DIR STF-DIR ist männlich
myCSharp.de-Mitglied

Dabei seit: 11.09.2006
Beiträge: 353
Entwicklungsumgebung: VS2008

Themenstarter Thema begonnen von STF-DIR

STF-DIR ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

ja genau, werd mal ein paar tutorials durchmachen um das ganze erst mal genau zu verstehen.
Ich danke dir bis dahin erst mal für die Hilfe !!

Eine letzte Frage hab ich aber noch.
Ich hab deinen Code oben mal in VS übernommen.
Leider meckert VS da immer an dem "Observable" rum und ich weiß nicht was ich da machen muss.
Eine fehlendes using scheint es nicht zu sein, oder doch ?
Mit dem Fehler nicht wirklich was anfangen. VS sagt nur, das Observable im aktuellen Context niht vorhanden ist... ?
Ich hab mal ein Bild davon angehanagen.

Ich wäre dir sehr dankbar, wenn du mir damit als letztes noch mal elfen könntest, denn da hing ich vorhin schon.

danke
Matthias

STF-DIR hat dieses Bild (verkleinerte Version) angehängt:
observable.jpg
Volle Bildgröße

24.01.2019 00:20 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 12.948
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Abt:
Insgesamt ist das alles in wenigen Zeilen zB mit Reactive Extensions umsetzbar.

 https://github.com/dotnet/reactive -> NuGet Paket.

Kannst aber auch drauf verzichten und statt dem Observerable nen Timer nehmen.
24.01.2019 00:54 Beiträge des Benutzers | zu Buddylist hinzufügen
STF-DIR STF-DIR ist männlich
myCSharp.de-Mitglied

Dabei seit: 11.09.2006
Beiträge: 353
Entwicklungsumgebung: VS2008

Themenstarter Thema begonnen von STF-DIR

STF-DIR ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

ach das ist ein Paket ... oh man.... ich hatte das gelesen, aber weil da "zum Beispiel" hab ich gar nicht in diese Richtung gedacht.

Danke dir !!

Matthias
24.01.2019 01:13 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 12.948
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Reactive Extension wird leider viel zu wenig beachtet, obwohl es Quellcode extrem vereinfacht und Dinge ermöglicht, für die man sonst ein riesen Topf an (teilweise umständlichen) Code benötigt (und diesen natürlich auch testen sollte).
Dabei hat sich jedoch Reactive Extensions für andere Sprachen schon viel weiter verbreitet - quasi kein Angular ohne NgRX - als aktuell noch in .NET-
24.01.2019 11:41 Beiträge des Benutzers | zu Buddylist hinzufügen
STF-DIR STF-DIR ist männlich
myCSharp.de-Mitglied

Dabei seit: 11.09.2006
Beiträge: 353
Entwicklungsumgebung: VS2008

Themenstarter Thema begonnen von STF-DIR

STF-DIR ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

danke für den Hinweis noch mal, ich schau es mir gerade genauer an.

Matthias
24.01.2019 12:16 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 7 Monate.
Der letzte Beitrag ist älter als 7 Monate.
Antwort erstellen


© Copyright 2003-2019 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 19.09.2019 21:28