Hallo liebe Gemeinde, ich möchte mich erst einmal einmal vorstellen da dies mein erster Beitrag in diesem (in Foren allgemein) ist. Ich möchte mich noch als Programmieranfänger bezeichnen. Vor zwei Jahren habe ich durch den Wunsch nach einer eigener Heimautomatisierung und einer Berufsunfähigkeit (also genug zeit für das neue Hobby), angefangen mir das Programmieren in C und C# beizubringen. Das Programm (man könnte es auch mein Übungsstück nennen) wuchs immer weiter, bis ich jetzt der Meinung war dass diese "Wurst" bevor sie noch größer wird einmal in Saubere geschrieben werden sollte. Und wie es immer ist, das letzte Schlüsselelement zum Fertigstellen des Grundsteins, kriege ich einfach nicht hin. Der Eventhandler. Was will ich mit dem Eventhandler eigtlich lösen: Der Multithread TcpServer tut sein dienst wunderbar und gibt auch schön alles was ich von den angebunden Geräten empfange brav an die klasse devider weiter. Diese soll nun die InStrings an die entsprechenden Klassen (für jedes angebundene Gerät eine Klasse) mit jeh einem Event weiterleiten. Der Versuch, angelehnt an dieses Beispiel https://msdn.microsoft.com/de-de/library/system.eventhandler%28v=vs.110%29.aspx sollte erstmal von der klasse "devider" (provider) ein event in der Klasse "solar" (suscriber) auslösen und mit den dazugehörigen Args den instring der in der Klasse "solar" landen soll, übergeben. Gesagt getan und siehe da es läuft nicht, nur einmal beim aufrufen der Form "solar" und danach nie wieder. Beim ganzen vor und zurückschrauben der Fehlersuche ist mir dann erstmal klar geworden was das Event eigentlich auslöst und warum es auch Callback genannt wird. Da beist sich die Katze in den Schwanz.... Daher zum Kern des Problems, so wie es jetzt ist (code hänge ich an) ist das ganze für mich unbrauchbar. Aber was ist die Lösung, ich hab grad null Ansätze. Sollte ich hier besser einfach Delegates verwenden oder habe ich das Thema Eventhandler falsch verstanden? Jedenfalls habe ich mir das gesamte Wochenende inklusive durch ehrgeiz provozierten schlafmangel um die Ohren gehauen und alles was der Freund Google so hergegeben hat gelesen und ausprobiert. Auch sämtliches hier aus dem Forum. Soviel zur Problembeschreibung aber Code sagt ja mehr als tausend Worte. vielen Dank schonmal im Vorraus und nun hier die Schnipsel von hier kommt der string//////////////////////// public class bridge { public static string outstring; public static string instring; #region set tcpServer public static void set_outstring(string value) { outstring = value; } public static void set_instring(string value) { instring = value; InStringCaster(); } #endregion #region set devider public static void InStringCaster() { if (instring != null) { string isc = instring; char splitter = '#'; string[] splitstring = isc.Split(splitter); switch (splitstring[0]) { case "Arduino1": devider dev1 = new devider(); dev1.dev1(instring); break; case "Arduino2": devider dev2 = new devider(); dev2.dev2(instring); // adminchar = splitstring[0]; break; case "Arduino3": devider dev3 = new devider(); dev3.dev3(instring); break; } devider op = new devider(); op.Admin(); } #endregion } } Diese Klasse soll das event in der Klasse "solar" auslösen sobald der instring für das gerät eintrifft und diesen übergeben class devider { #region Strom protected virtual void OnInString_powermeter_main_Reached(powermeter_mainArgs e) { EventHandler<powermeter_mainArgs> handler = InString_powermeter_main_Reached; if (handler != null) { handler(this, e); } } public event EventHandler<powermeter_mainArgs> InString_powermeter_main_Reached; public void dev1(string instring) { powermeter_mainArgs powermeter_mainargs = new powermeter_mainArgs(); powermeter_mainargs.InString_powermeter_main = instring; OnInString_powermeter_main_Reached(powermeter_mainargs); } #endregion #region solar public void dev2(string instring) { SolarArgs solarargs = new SolarArgs(); solarargs.InString_Solar = instring; OnInString_Solar_Reached(solarargs); //MessageBox.Show("void dev2"); } void OnInString_Solar_Reached(SolarArgs e) { EventHandler<SolarArgs> handler = InString_Solar_Reached; try { handler(this, e); MessageBox.Show("handler is != null"); } catch { MessageBox.Show("handler is null"); } } public event EventHandler<SolarArgs> InString_Solar_Reached; #endregion #region door public void dev3(string instring) { DoorArgs Doorargs = new DoorArgs(); Doorargs.InString_Door = instring; OnInString_Door_Reached(Doorargs); } void OnInString_Door_Reached(DoorArgs e) { EventHandler<DoorArgs> handler = InString_Door_Reached; handler.Invoke(this, e); } public event EventHandler<DoorArgs> InString_Door_Reached; #endregion #region admin public void Admin() { /* AdminArgs adminargs = new AdminArgs(); adminargs.InString_Admin = bridge.instring; adminargs.OutString_Admin = bridge.outstring; OnInString_Admin_Reached(adminargs); */ } #endregion } in dieser Form soll durch das event von der klasse "devider" der void InStringCaster aufgerufen werden um den instring zu verarbeiten public partial class solar : Form { #region deklaration public string isc2; public float grid_voltage; float grid_frequency; float AC_output_voltage; float AC_output_frequency; float Battery_voltage; float PV_input_voltage1; float Battery_input_voltage_SCC; int SBU_priority_version = 0; int config_Status = 0; int SCC_firmware_version = 0; int Load_status = 0; int battery_voltage_steady_charging = 0; string Charging_Status_Text = ""; long AC_output_apparent_power; long AC_output_active_power; int Output_load_percent; float BUS_voltage; int Battery_charging_current; int Battery_capacity; float Inverter_heatsink_temperature; int PV_input_current_for_battery; int Battery_discarge_current; string PIP_Output_mode; string test = "0"; string test1 = "0"; string test2 = "0"; string test3 = "0"; string test4 = "0"; public static string solarinstring; public static string InStringCasters; #endregion public solar() { InitializeComponent(); devider dev = new devider(); dev.InString_Solar_Reached += InString_Solar_Reached; } #region event static void InString_Solar_Reached(object sender, SolarArgs e) { // InStringCaster(e.InString_Solar); InStringCasters = e.InString_Solar.ToString(); MessageBox.Show("Event Solar triggerd"); } #endregion #region debug instring public void InStringCaster(string InString) { string[] isc; string OK = "(ACK9 "; char splitter = '#'; isc = InString.Split(splitter); try { if(isc[0]=="Arduino2") { switch (isc[1]) { case "QPIGS": if (isc[2].Length > 0) { QPIG(isc[2]); } break; case "QMOD": QMOD(isc[2]); break; case "PCPuf": if (isc[2] == OK) MessageBox.Show("change accepted"); break; case "PCPsf": if (isc[2] == OK) { } MessageBox.Show("change accepted"); break; case "PCPsu": if (isc[2] == OK) MessageBox.Show("change accepted"); break; case "PCPso": if (isc[2] == OK) MessageBox.Show("change accepted"); break; case "POPuf": if (isc[2] == OK) MessageBox.Show("change accepted"); break; case "POPsf": if (isc[2] == OK) { } MessageBox.Show("change accepted"); break; case "POPsbu": if (isc[2].Length > 0) { if (isc[2] == OK) MessageBox.Show("change accepted"); } break; case "Hello Server": //MessageBox.Show("solar inverter connected"); break; } } } catch{ } } }
Hi, ich glaube, Du hast eine komplett falsche Vorstellung davon, was ein Event ist und wann man diesen sinnvoll einsetzen kann. Ein Event ist erst einmal nichts anderes als eine Liste von Delegaten, also Zeiger auf Funktionen von Klasseninstanzen. Events (und Delegaten) sind immer dann sinnvoll, wenn die Klasse oder Komponente nicht weiss, wer sie mal später verwendet, man aber sicher ist, dem Benutzer der Komponente etwas mitteilen zu wollen. Gerade Oberflächenkomponenten eignen sich dafür besonders gut, daher haben diese stets viele Events, an die man sich "dranhängen" kann. Das geht nicht nur mit einer Funktion, sondern mit (nahezu) beliebig vielen! Events werden immer zur LAUFZEIT mit Delegaten bestückt, also z.B. BlablaEvent += MeineFunktionInEinerKlasse; Das kann ich in Deinen Quellen gar nicht finden, Deine Events sind schlicht leer! Ich habe den zudem den Eindruck, dass Du das Ganze viel zu kompliziert angehst. Gib Deinen Objekten entsprechende Properties und setze die, wenn Daten empfangen werden. Du schreibst ja keine Komponenten, oder? Gruß, Oliver
hi, erstmal danke für die schnelle Antwort. Klar da hast du natürlich recht, wie gesagt das ist der erste Versuch einen Eventhandler zu nutzen und zugegeben der code sieht natürlich verkompliziert aus, das sind alles gesäuberte Fragmente vom alten Programm. Die sollen nur dazu dienen das alles neu zu schreiben. Dazu kommt noch, dass ich vergessen hab die "public class SolarArgs : EventArgs { public string InString_Solar { get ; set ; } }" in den Post einzufügen. Es geht sich grade nur um den "Grundstein" in class solar : Form den void instringcaster aufzurufen und den instring zu verarbeiten. "Events (und Delegaten) sind immer dann sinnvoll, wenn die Klasse oder Komponente nicht weiss, wer sie mal später verwendet, man aber sicher ist, dem Benutzer der Komponente etwas mitteilen zu wollen." Trifft hier ja auch zu. Den devider soll es nur einmal geben, für alle Forms. Man könnte das sicher umgehen in dem man einfach ALLES neuschreibt und ganz anders aufbaut aber der TCPServer und die Forms stehen(waren im code jetzt nicht sichtbar) und will zumindest an dem TCPServer nichts mehr ändern. Richtig ist auch das Event übertrieben sind aber es kann ja nicht verkehrt sein events nutzen zu können da das Programm ja noch wesentlich mehr Teile hat und in Zukunft noch mehr dazu kommen sollen. Im alten Programm lief das beim ersten Versuch, habe mich daher auch nicht näher damit beschäftigt und wollte das jetzt wieder so übernehmen, jedoch war es nicht reproduzierbar. Verstehe nur deine Aussage nicht dass der Event leer ist. Dein Beispiel "BlablaEvent += MeineFunktionInEinerKlasse;" findet man ja in class solar public solar() { InitializeComponent(); devider dev = new devider(); dev.InString_Solar_Reached += InString_Solar_Reached; } Das Beispiel von MSDN funktioniert , es ist also alles da was man braucht. Ob es für meine Zwecke brauchbar ist, ist dann wieder ne andere Frage und kann ich auch noch nicht wirkich beurteilen. Was für eine Lösung würde denn ein erfahrener Programmierer andenken ? edit: Es funktioniert jetzt. Ich habe in class devider public static event EventHandler<SolarArgs> InString_Solar_Reached; als static geändert und in class solar public solar() { InitializeComponent(); devider.InString_Solar_Reached += InString_Solar_Reached; } wird kein neues objekt mehr erstellt. Meintest du das mit "leeres Event" ? Was hälst du davon ? egal wie ....Danke auf jeden Fall für die Hilfe
:
Bearbeitet durch User
1 | public solar() |
2 | { |
3 | InitializeComponent(); |
4 | |
5 | devider dev = new devider(); |
6 | dev.InString_Solar_Reached += InString_Solar_Reached; |
7 | } |
Hmmm ... du erzeugst hier eine neue Instanz von devider, hängst dich in InString_Solar_Reached ein und wirfst die Instanz gleich wieder weg. dev sollte eigentlich Klassenmember sein, keine lokale Variable. "Ob es für meine Zwecke brauchbar ist, ist dann wieder ne andere Frage und kann ich auch noch nicht wirkich beurteilen." Events sind schon ok. "Ich habe in class devider public static event EventHandler<SolarArgs> InString_Solar_Reached; als static geändert" Man muss nicht alles static machen, was bei drei nicht auf dem nächsten Baum ist ... ;). Wie gesagt, verwende ganz normale Klassenmember. Ich verstehe u.a. auch noch nicht ganz, warum du immer wieder neue Instanzen von devider ("divider", ich würde es aber evtl. eher "Distributor", "Broker" o.ä. nennen) erzeugst und wieder wegschmeißt: devider dev1 = new devider(); dev1.dev1(instring); devider dev2 = new devider(); dev2.dev2(instring); devider dev3 = new devider(); dev3.dev3(instring); devider op = new devider(); op.Admin(); Es sollte doch eigentlich nur eine Instanz davon geben, die eben alles auf die Empfänger verteilt (falls ich dein Konzept richtig verstanden habe).
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.