Wie gehts das mit Delegate ?
-
Hallo Forumleser,
ich bin gerade dabei ein Prgramm zuschreiben was Daten über die serielle Schnittstelle enmpfängt. Allerdings verzweifel ich gerdae daran die Daten in die Anzeigeelemnte zu bekommen. Da die MSDN-Hilfe sehr dürftig ist habe ich schon im Openbook von Galileo geschaut aber das hat auch nicht wirklich geholfen.
Hier mal mein letzter Versuch:
(Bekomme zur Laufzeit immer eine Exception)using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace Fernsteuerung { public partial class Form1 : Form { private int Byte_Zaehler = 0; private byte[] Daten = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; public delegate void DataReceived(byte data); public Form1() { InitializeComponent(); Channel1_value.Text = Channel1.Value.ToString(); Channel2_value.Text = Channel2.Value.ToString(); } private void Channel1_Scroll(object sender, EventArgs e) { byte[] Daten = new byte[5]; Channel1_value.Text = Channel1.Value.ToString(); Daten[0] = (byte)'S'; Daten[1] = (byte)'1'; Daten[2] = (byte)Channel1.Value; Daten[3] = (byte)10; Daten[3] = (byte)13; if (serialPort1.IsOpen == true) serialPort1.Write(Daten,0,5); } private void Channel2_Scroll(object sender, EventArgs e) { byte[] Daten = new byte[5]; Channel2_value.Text = Channel2.Value.ToString(); Daten[0] = (byte)'S'; Daten[1] = (byte)'2'; Daten[2] = (byte)Channel2.Value; Daten[3] = (byte)10; Daten[3] = (byte)13; if (serialPort1.IsOpen == true) serialPort1.Write(Daten,0,5); } private void Connect_Click(object sender, EventArgs e) { serialPort1.PortName = Portname.Text; serialPort1.BaudRate = System.Int32.Parse(Baudrate.Text); try { serialPort1.Open(); } catch (System.Exception) { MessageBox.Show("Fehler beim öffnen der Schnittstelle!", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); } if (serialPort1.IsOpen == true) { Connect.Enabled = false; Disconnect.Enabled = true; } } private void Disconnect_Click(object sender, EventArgs e) { serialPort1.Close(); if (serialPort1.IsOpen == false) { Connect.Enabled = true; Disconnect.Enabled = false; } } private void DataWorker(byte Data) { if (Data == (byte)'R') { Byte_Zaehler = 0; Daten[Byte_Zaehler++] = Data; } else if (Byte_Zaehler < 6) { Daten[Byte_Zaehler++] = Data; if (Byte_Zaehler == 6) { switch (Daten[1]) { case (byte)'1': LV.Text = BitConverter.ToSingle(Daten, 2).ToString(); break; case (byte)'2': RV.Text = BitConverter.ToSingle(Daten, 2).ToString(); break; case (byte)'3': LH.Text = BitConverter.ToSingle(Daten, 2).ToString(); break; case (byte)'4': RH.Text = BitConverter.ToSingle(Daten, 2).ToString(); break; } } } } private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { DataReceived process = new DataReceived(DataWorker); process((byte)serialPort1.ReadByte()); } } }
-
Servus,
sehr dürftig was du hier an Informationen gibts. Der Quellcode interessiert hier nicht direkt, sondern eher die Exception die bei dir fliegt. Die MSDN ist gerade was den Fall betrifft, alles andere als dürftig.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vcrefTheDelegateType.asp
Aber ich zeige dir mal im Crashkurs, wie soetwas funktionieren kann:
Wenn du einen eigenen Delegaten erstellen willst:
Deklarieren
public delegate void ItemEventHandler();
Definieren
private ItemEventHandler OnItemAdded; private void AddItem() { // Rubbeldiekatz, Mach was // EDIT: Natürlich musst du hier etwas mit deinem Control anstellen int i = 0; i++; }
Initialisieren
this.OnItemAdded = new ItemEventHandler(AddItem);
Aufruf
this.deinControl.Invoke(this.OnItemAdded);
mfg
Hellsgore
-
Hellsgore schrieb:
private ItemEventHandler OnItemAdded; private void AddItem() { // Rubbeldiekatz, Mach was // EDIT: Natürlich musst du hier etwas mit deinem Control anstellen int i = 0; i++; }
nach jedem aufruf von AddItem() ist der Counter wieder 1, ist das sinnvoll? sollte i nicht ausserhalb initialisiert werden?
-
Servus,
ich glaube du hast hier etwas falsch verstanden....
Ich hätte dort auch "MOOH" reinschreiben können. Es soll nur zeigen das in dieser Methode irgendwas gemacht werden soll. Das mein Beispiel mit "i" nicht sinnvoll ist, dass sollte eigentlich jedem direkt aufgefallen sein.mfg
Hellsgore
-
Der Link ist perfekt, der ist sowas von nichts aussagend, 10 Zeilen Besipiel ohne Kommentierung. Echt toll.
Schaut man bei der Hilde zur SerialPort Komponente. "Das folgende Beispiel zeigt ..." und wo ist das Beispiel? Super!
So genug aufgeregt.
Die Exception kann ich gerade nicht nennen, weil ich am Code schon soviel rumgebastelt habe, das ich nicht mehr weiss was ich ändern muss um die Exception zu bekommen. Es war aber irgendwas mit Zugriff auf Componente aus fremden Thread.
Nun zu deinem Post Hellsgore.
Wie du sehen kannst ne Deklaration habe ich. Heist bei mir DataReceivedDie Defintion habe ich in der Methode die das DataReceived-Event von der Comport-Componente und heist process.
Ist das falsch, muss die in der Klasse definiert werden ?Dei Methode die du AddItem genannt hast, heist bei mir DataWorker.
Initialisierung habe ich ebenfalls im Event-Handler ist das auch falsch ?
Aufruf ok den habe ich verpennt. Habe ihn aber nun in dem Eventhandler eingefügt und bekomee nun folgende Exception TargetParameterCountException.
Das zweite was ich nicht kapiere ist, wie bekomme ich die Daten aus dem Eventhandler in meine Methode die den Componenten die Wert zuweist.
Hier noch einen Ausschnitt des Codes wie ich es im Moment habe.
Deklarieren
public partial class Form1 : Form { private int Byte_Zaehler = 0; private byte[] Daten = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; public delegate void DataReceived(string data, byte compid);
Definieren
private void DataWorker(string Data, byte CompID) { switch (CompID) { case (byte)'1': LV.Text = Data; break; case (byte)'2': RV.Text = Data; break; case (byte)'3': LH.Text = Data; break; case (byte)'4': RH.Text = Data; break; } }
Initialisieren + Aufruf
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { byte Data = (byte)serialPort1.ReadByte(); if (Data == (byte)'R') { Byte_Zaehler = 0; Daten[Byte_Zaehler++] = Data; } else if (Byte_Zaehler < 6) { Daten[Byte_Zaehler++] = Data; DataReceived p = new DataReceived (DataWorker/*(BitConverter.ToSingle(Daten, 2).ToString(), Daten[1])*/); if (Byte_Zaehler == 6) { switch (Daten[1]) { case (byte)'1': LV.Invoke(p); break; case (byte)'2': RV.Invoke(p); break; case (byte)'3': LH.Invoke(p); break; case (byte)'4': RH.Invoke(p); break; } } } }
Ich hoffe ihr könnt mir weiterhelfen.
Mfg
DarkMight1
-
Servus,
ich habe nicht sehr viel Zeit aber ich kann dir noch sagen, dass ihm die Daten die du übergeben willst einfach in der Methode fehlen. Er weiss nicht was er machen soll.
Wenn du dem Link folgst und ganz unten auf "Delegate Tutorial" klickst, dann bekommst du auch mehr als 10 Zeilen.
Ich kann dir erst wieder am Montag weiterhelfen, dann werden wir mal den Fehler analysieren. Die Geschichte ist nicht so schwer. Vielleicht wird dir aber zwischenzeitlich ein Anderer weiterhelfen.
mfg
Hellsgore
-
Servus,
so... wie versprochen eine kurze Analyse. Dem Aufruf Invoke vom Control musst du natürlich auch noch die Parameter mit übergeben, sonst geht das Ganze in die Hose. Ich habe mal auf die Schnelle deine DataRecieve Geschichte überarbeitet. Das Ganze solltest du einfach mal durchtesten.
// Das hier irgendwo in die Initialisierung // Aber nicht jedes mal neu Initialisieren wenn Recieved // aufgerufen wird. DataReceived p = new DataReceived(this.DataWorker); private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { byte Data = (byte)serialPort1.ReadByte(); if (Data == (byte)'R') { Byte_Zaehler = 0; Daten[Byte_Zaehler++] = Data; } else if (Byte_Zaehler < 6) { Daten[Byte_Zaehler++] = Data; // Hier kommen deine Daten rein string data = "Mooh"; // Hier deine ID byte compid = 0x01; if (Byte_Zaehler == 6) { switch (Daten[1]) { case (byte)'1': LV.Invoke(p, new object[] { data, compid }); break; case (byte)'2': RV.Invoke(p, new object[] { data, compid }); break; case (byte)'3': LH.Invoke(p, new object[] { data, compid }); break; case (byte)'4': RH.Invoke(p, new object[] { data, compid }); break; } } } }
mfg
Hellsgore
-
Danke jetzt habe ich es endlich kapiert.
Allerdings habe ich nun neue Probleme. Ich starte das Programm aus der IDE raus und lasse mir die Daten auf der Console ausgeben, unter anderen auch den 'Index' und das Zeichen aus. Allerdings geht der Index nicht wie erwartet bis auf 0 runter sondern nur 2 Zeichen und dann geht der Index wieder nach oben und es werden auch nicht alle Zeichen ausgegeben. Ausserdem hängt sich das Programm auf, aber nur wenn ich es aus der IDE aus starte wenn ich es von der Festplatte starte läuft das Programm allerdings kann ich die Ausgabe nicht kontrollieren, weil ich nicht wiess wo die Ausgabe landet.
Hier mal die Strings die empfangen werden sollten
Riffff // i = index 1-4, ffff = bytes eines floats
zur Zeit beträgt der float-Wert 0.0
Hier der Code wie er im Moment ist:
namespace Fernsteuerung { public partial class Form1 : Form { public delegate void DataReceived(char data); private static int Byte_Zaehler = 0; private static byte[] Daten = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; private DataReceived parser; public Form1() { InitializeComponent(); Channel1_value.Text = Channel1.Value.ToString(); Channel2_value.Text = Channel2.Value.ToString(); parser = new DataReceived(this.DataParser); }
private void DataParser(char Data) { Console.WriteLine(Data); if (Data == 'R') { Byte_Zaehler = 0; Daten[Byte_Zaehler++] = (byte)Data; } else if (Byte_Zaehler < 6) { Daten[Byte_Zaehler++] = (byte)Data; if (Byte_Zaehler == 6) { switch (Daten[1]) { case (byte)'1': Console.WriteLine(BitConverter.ToString(Daten, 2)); LV.Text = BitConverter.ToString(Daten); break; case (byte)'2': Console.WriteLine(BitConverter.ToString(Daten, 2)); RV.Text = BitConverter.ToString(Daten); break; case (byte)'3': Console.WriteLine(BitConverter.ToString(Daten, 2)); LH.Text = BitConverter.ToString(Daten); break; case (byte)'4': Console.WriteLine(BitConverter.ToString(Daten, 2)); RH.Text = BitConverter.ToString(Daten); break; } } } }
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { for (int i = serialPort1.BytesToRead; i >= 0; i--) { Console.Write(i + " "); this.Invoke(parser, new object[] { (char)serialPort1.ReadChar() }); } }