Delegate Funktion an Konstruktor übergeben
-
sorry
-
Nur zwei kleine Anmerkungen:
Es ist nicht gut der Hilfsklasse eine Referenz auf die Form zu übergeben. Erstelle lieber innerhalb von Rs232Thread ein event das die Form abonniert.
Man sollte Threads nicht mit Thread.Abort(); beenden. Das geht sehr viel sauberer und kontrollierter:
http://www.albahari.com/threading/part3.aspx#_Safe_Cancellation
-
... Erstelle lieber innerhalb von Rs232Thread ein event das die Form abonniert.
Zeig mal wie das geht, danke!
-
Nein machen wir nicht, bitte! Also sachmal ehrlich, bist du zu Faul um selber zu lernen?!
-
Ein Versuch war es ja Wert
Werde dann mal selber suchen.
-
hermes schrieb:
Zeig mal wie das geht, danke!
Hi hermes, ich kann dir folgende Seite empfehlen wenn du zum Thema Events mehr erfahren möchtest: http://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx
Gruß!
-
Vielen Dank
-
Habe das ganze nun mal ausprobiert
public class Rs232Thread { .......... // Thread public void Rs233ThreadFunction() { while (true) { try { RxLenght = Rs232.BytesToRead; if (RxLenght != 0) { RxCnt++; _Rs232EventArgs.Rs232Data = Rs232.ReadByte(); if (Rs232Receive != null) Rs232Receive(this, _Rs232EventArgs); } } catch (Exception e) { // Hir kommt die Exeption } } } .......... } public partial class Form1 : Form { ....................... // Hier die Event Funktion public void ReceiveRs232(object sender, R232EventArgs e) { RxBuffer[BufferIndex] = Convert.ToByte(e.Rs232Data); setToolStripMenuItem.Enabled = true; Rs232.Rs232WriteByte(TxBuffer[BufferIndex]); return; } ............ }
Die Event Fuktion public void ReceiveRs232(object sender, R232EventArgs e) wird ausgeführt es kommt dann aber folgende Exeption im Thread
"Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement menuStrip1 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde."
Was muss ich da noch beachten?
-
Was muss ich da noch beachten?
Threading. Es gibt ein GUI Thread (mit deinem sichtbaren Fenster) und einen anderen Thread, der versucht etwas in Fenster ändern).Siehe http://msdn.microsoft.com/de-de/library/system.windows.forms.control.invoke.aspx
-
public partial class Form1 : Form { private void Form1_Load(object sender, EventArgs e) { ....... Rs232 = new Rs232Thread(this); Rs232.Rs232Receive += ReceiveRs232; ........ } public void ReceiveRs232(object sender, R232EventArgs e) { ..... setToolStripMenuItem.Enabled = true; infoToolStripMenuItem.Enabled = true; Offline = false; RxBuffer[BufferIndex] = Convert.ToByte(e.Rs232Data); Rs232.Rs232WriteByte(TxBuffer[BufferIndex]); } } public class R232EventArgs : EventArgs { public int RxLenght; public int Rs232Data; } public class Rs232Thread { public delegate void ReceivedEventHandler(object sender, R232EventArgs e); public event ReceivedEventHandler Rs232Receive; private R232EventArgs _Rs232EventArgs; private Form CtrForm; private Thread Thread; private delegate void DelegateReceiveRs232(R232EventArgs e); private DelegateReceiveRs232 Rs232ReceiveDelegate; public Rs232Thread(Form _CtrForm) { CtrForm = _CtrForm; Rs232ReceiveDelegate = new DelegateReceiveRs232(Rs232Rx); Rs232Receive = null; _Rs232EventArgs = new R232EventArgs(); Rs232 = new SerialPort(); Rs232CheckPorts(); } public bool InitRs232(String Port, int Baudrate) { ..... Thread = new Thread(new ThreadStart(Rs233ThreadFunction)); Thread.Start(); ....... } public void Rs233ThreadFunction() { while (true) { try { RxLenght = Rs232.BytesToRead; if (RxLenght != 0) { RxCnt++; _Rs232EventArgs.Rs232Data = Rs232.ReadByte(); CtrForm.Invoke(Rs232ReceiveDelegate, new Object[] { _Rs232EventArgs }); } } catch (Exception e) { RxCnt = 0; } } } protected void Rs232Rx(R232EventArgs e) { if (Rs232Receive != null) Rs232Receive(this, e); } }
So funktionierts, oder könnte es da irgend welche Probleme geben?
-
Das ist nicht gut.
Du musst dich entscheiden, entweder Control.Invoke oder Events (besser hier Events).z.B.: (ungetestet)
// Zeile 10: Rs232 = new Rs232Thread(); Rs232.Rs232Receive += ReceiveRs232; /*...*/ // BESSER: nicht public private void ReceiveRs232(object sender, R232EventArgs e) { // Ruft deinen Code im GUI-Context auf (geht besser über extrafunktion aber egal. if(InvokeRequired) { Invoke(ReceiveRs232, new Object[] {e}); return; } // dein code }
Ein paar Anmerkungen:
- schau dir mal den System.Windows.Forms.Backgroundworker an.
while (true)
catch (Exception e)
ist schlechter Stiel, genaue Fehlerklassen angeben. (Es gibt vielliecht Fehler, die du da nicht abfangen willst: z.B.:
Wenn - warum auch immer - der Stack voll ist und zwischen 73 - 80 eine Stackoverflow-Exception auslöst wird, kann dein Programm in einer Endlosschleife geraten)- Membervariablen kleinschreiben (Rs232Thread.Thread, Form1.Rs232 )
- eine Variable genau so wie ihren Typ zu benennen, zeugt nicht von wenig Fantasie. (macht auch ggf. Schwierigkeiten
(Gruß C++CLI)) public int RxLenght;
kapseln (public int Length { get; private set; } und im Konstruktor zuweisen)- Delegates außerhalb der Klasse
- Das Delegate im Thread bruchst du nicht, nimm
EventHandler<R232EventArgs>
- EventArgs jedesmal neu generieren (Vielleicht will der Empfänger die ja speichern - warum auch immer) und nicht als Instanzvariable
- Auf
Nullpointer
prüfen
Edit: Schlechtschreibkorretur