| |
VB.NET - Ein- und UmsteigerProblem mit Aktualisierung einer Textbox bei seriellem Empfang | | | Autor: Lupus52 | Datum: 16.12.16 12:41 |
| Hallo,
ich habe eine Klasse Form1 und eine Klasse Class_COM. 2 separate Dateien. Form1.vb und Class_COM.vb
Das ganze gehört zu einer Mess-Software.
Habe das ganze runtergebrochen bis auf Minimum und finde den Fehler nicht.
Unter "Form" habe ich eine Form mit Button "Senden" und eine Textbox für die Ausgabe.
Unter Class_Com habe ich 4 Subs bzw. Funktionen.
OpenCom
WriteCom
ReadCom
CloseCom
Nach dem Druck auf Senden wird ein Steuer-String für ein Gerät korrekt gesendet.
Die Antwort wird auch korrekt empfangen wie man an einer Debugausgabe unter Read_Com sieht.
Parallel zur Debugausgabe soll der String in Form1.Textbox2.Text landen. Macht er aber nicht. Es passiert schlicht gar nichts in der Anzeige der Textbox. Wobei aber das Event "Textchangend" dieser Textbox ausgelöst wird! D.h. die Box hat was bekommen.
Wenn ich dieselbe Ausgabezeile an beliebige andere Stellen im Programm plaziere geht es. Z.b. unter OpenCom. Dann schreibt es "open" in die Textbox.
Nur die empfangenen Daten bzw. ein Dummytext "123" kommt nicht zur Anzeige.
Ein Refresh oder Update der Textbox bringt auch nichts.
Mein Latein ist am Ende
Imports System.IO.Ports
Imports System.Threading
Public Class Class_COM
Public Shared _serialPort As SerialPort
Public Function OpenCom() As Boolean
_serialPort = New SerialPort()
_serialPort.PortName = "COM2"
_serialPort.BaudRate = 115200
_serialPort.Parity = 0
_serialPort.DataBits = 8
_serialPort.StopBits = 1
_serialPort.RtsEnable = True
_serialPort.DtrEnable = True
_serialPort.Handshake = 0
_serialPort.ReadTimeout = 500
_serialPort.WriteTimeout = 500
AddHandler _serialPort.DataReceived, AddressOf DataReceivedHandler
Try
_serialPort.Open()
Catch ex As Exception
MsgBox("Comport " & Form1.Comport & " konnte nicht geöffnet werden")
Return 0
End Try
If _serialPort.IsOpen Then
Form1.TextBox2.Text = "open"
Return True
Else
Return 0
End If
End Function
Public Sub WriteCom(message)
_serialPort.WriteLine(message)
End Sub
Public Function CloseCom() As Boolean
_serialPort.Close()
Form1.TextBox2.Text = "closed"
End Function
Public Function comstatus() As Boolean
Return _serialPort.IsOpen
End Function
Private Shared Sub DataReceivedHandler(sender As Object, e As _
SerialDataReceivedEventArgs)
Dim sp As SerialPort = CType(sender, SerialPort)
Dim indata As String = sp.ReadExisting()
Console.Write("RX: ")
Console.WriteLine(indata)
Form1.TextBox2.Text = "123"
End Sub
End Class | |
Re: Problem mit Aktualisierung einer Textbox bei seriellem Empfang | | | Autor: Lupus52 | Datum: 16.12.16 15:03 |
| Hallo
>Vielleicht solltest Du den DataReceivedHandler dann auch Public machen...
Warum? Der Empfänger funktioniert doch. Die Routine ist ja nur lokal aktiv. Bzw. sie schreibt gezielt mit Form1.Textbox2.Text eben in die Textbox. Bzw. sie sollte es.
Sie schreibt auch offensichtlich was in Richtung Textbox. Das Textchanged-Ereignis der Box wird ausgelöst! Nur es erscheint kein Inhalt. Aber das schrieb ich schon.
Habe es auch mit Public versucht. Es ändert sich nichts.
>Wieso steht da was von Console drin? Du arbeitest doch mit Forms, oder?
Weil ich damit ins Ausgabefenster schreibe zwecks Debugging. Im Ausgabefenster erscheint mein empfangener Text. Aber das schrieb ich schon. UNd das hat auch nichts mit der Textbox zu tun.
Wenn ich Debug.write nehme erhalte ich keine Ausgabe im Ausgabefenster. Trotz gewählter Ausgabe "Debuggen". Also nehme ich Console. Da bin ich durch Zufall drauf gekommen. Keine Ahnung warum das so ist.
Frage: Ich finde hier keine Zitierfunktion. Gibt es die nicht wei in anderen Foren oder sehe ich sie bloß nicht? | |
Re: Problem mit Aktualisierung einer Textbox bei seriellem Empfang | | | Autor: sv00010 | Datum: 16.12.16 17:42 |
| Lupus52 schrieb:
Zitat: | |
Frage: Ich finde hier keine Zitierfunktion. Gibt es die nicht
wei in anderen Foren oder sehe ich sie bloß
nicht? | |
Zuerst auf Antworten klicken, dann kommt das Fenster zu schreiben und dann unten rechts neben dem Senden-Button, ist der Zitieren-Button. | |
Re: Problem mit Aktualisierung einer Textbox bei seriellem Empfang | | | Autor: Lupus52 | Datum: 16.12.16 18:29 |
| Hallo,
wenn ich das Antwortenfeld aufhabe, gibt es rechts unten nur nur "Senden" und "Vorschau" | |
Re: Problem mit Aktualisierung einer Textbox bei seriellem Empfang | | | Autor: sv00010 | Datum: 16.12.16 19:33 |
| Lupus52 schrieb:
Zitat: | | Hallo,
wenn ich das Antwortenfeld aufhabe, gibt es rechts unten nur
nur "Senden" und "Vorschau" | |
Du kannst auch den Text per copy & paste einfügen und am Anfang des zu zitierenden Text "quote" reinschreiben, mit [] herum und am Ende des zu zitierenden Textes "/quote" mit [] herum.
Ich kann das leider hier nicht richtig reinschreiben, weil das sonst als zitieren angezeigt wird.
https://www.bbcode.org/examples/?id=8 | |
Re: Problem mit Aktualisierung einer Textbox bei seriellem Empfang | | | Autor: Lupus52 | Datum: 19.12.16 00:55 |
| sv00010 schrieb:
Zitat: | | Lupus52 schrieb:
Zitat: | | Hallo,
wenn ich das Antwortenfeld aufhabe, gibt es rechts unten nur
nur "Senden" und
"Vorschau" | |
Du kannst auch den Text per copy & paste einfügen und am
Anfang des zu zitierenden Text "quote"
reinschreiben, mit [] herum und am Ende des zu zitierenden
Textes "/quote" mit [] herum.
Ich kann das leider hier nicht richtig reinschreiben, weil
das sonst als zitieren angezeigt wird.
https://www.bbcode.org/examples/?id=8 | |
Danke - inzwischen bin ich hinter den "Forums-BUG" gekommen. Es gibt 2 Ansichtformen: Gesamtansicht und Threadansicht. Wenn ich bei der Gesamtansicht konkret bei einem Beitrag dazu auf "Antworten" klicke gibt es keinen Zitierbutton. Bei der Threadansicht gibt es ihn. | |
Re: Problem mit Aktualisierung einer Textbox bei seriellem Empfang | | | Autor: Manfred X | Datum: 19.12.16 06:20 |
| Hallo!
Du greifst per "Form1" offenbar auf die Defaultinstanz des
Formulars zu. Allem Anschein nach ist das nicht die Instanz der
Form-Klasse, deren Textbox Du ansprechen möchtest.
Es gibt diverse Grundregeln im OOP.
Eine lautet sinngemäß, daß Klassen per Methodenaufruf mit untergeordneten
Klassen kommunizieren und die untergeordneten Klassen Ereignisse
verwenden, um Informationen zu liefern.
Man sollte NIE von außen auf Controls eines Formulars zugreifen.
Deine Com-Klasse sollte deshalb so oder ähnlich konstruiert werden:
Option Strict On : Option Explicit On
Imports System.IO.Ports
Imports System.Threading
Public Class Class_COM
Private WithEvents _serialPort As SerialPort
Public Event ComStateChanged(ByVal sender As Object, e As EventArgs)
Public Event Datareceived(ByVal sender As Object, data As String)
Public Function OpenCom(ByVal Comport As String) As Boolean
_serialPort = New SerialPort
_serialPort.PortName = "COM2"
_serialPort.BaudRate = 115200
_serialPort.Parity = 0
_serialPort.DataBits = 8
_serialPort.StopBits = StopBits.One
_serialPort.RtsEnable = True
_serialPort.DtrEnable = True
_serialPort.Handshake = 0
_serialPort.ReadTimeout = 500
_serialPort.WriteTimeout = 500
Try
_serialPort.Open()
If _serialPort.IsOpen Then
RaiseEvent ComStateChanged(Me, EventArgs.Empty)
End If
Return _serialPort.IsOpen
Catch ex As Exception
Return False
End Try
End Function
Public Function WriteCom(ByVal message As String) As Boolean
Try
_serialPort.WriteLine(message)
Return True
Catch
Return False
End Try
End Function
Public Function CloseCom() As Boolean
Try
_serialPort.Close()
RaiseEvent ComStateChanged(Me, EventArgs.Empty)
Return True
Catch
Return False
End Try
End Function
Public Function comstatus() As Boolean
Return _serialPort.IsOpen
End Function
Private Sub DataReceivedHandler(sender As Object, e As _
SerialDataReceivedEventArgs) Handles _serialPort.DataReceived
Dim sp As SerialPort = CType(sender, SerialPort)
Dim indata As String = sp.ReadExisting()
RaiseEvent Datareceived(Me, indata)
End Sub
End Class Im Formular werden die Ereignisse verarbeitet. Etwa so ...
Public Class frmCom
Dim WithEvents myCom As New Class_COM
Dim WithEvents btnSenden As New Button _
With {.Parent = Me, .Text = "Senden"}
Dim txtState As New TextBox _
With {.Parent = Me, .Top = 50}
Dim txtData As New TextBox _
With {.Parent = Me, .Top = 100}
Private Sub frmCom_Load(sender As System.Object, _
e As System.EventArgs) Handles MyBase.Load
If Not myCom.OpenCom("xxxx") Then
MsgBox("Port kann nicht geöffnet werden")
End If
End Sub
Private Sub mycom_ComStateChanged(sender As Object, _
e As System.EventArgs) Handles myCom.ComStateChanged
txtState.Text = If(myCom.comstatus, "Open", "Close")
End Sub
Private Sub mycom_Datareceived(sender As Object, _
data As String) Handles myCom.Datareceived
txtData.Text = data
End Sub
Private Sub btnSenden_Click(sender As Object, _
e As System.EventArgs) Handles btnSenden.Click
myCom.WriteCom("XXX")
End Sub
End Class | |
Re: Problem mit Aktualisierung einer Textbox bei seriellem Empfang | | | Autor: Lupus52 | Datum: 19.12.16 10:41 |
| Manfred X schrieb:
Zitat: | | Hallo!
Du greifst per "Form1" offenbar auf die
Defaultinstanz des
Formulars zu. Allem Anschein nach ist das nicht die Instanz
der
Form-Klasse, deren Textbox Du ansprechen möchtest.
Es gibt diverse Grundregeln im OOP.
Eine lautet sinngemäß, daß Klassen per Methodenaufruf mit
untergeordneten
Klassen kommunizieren und die untergeordneten Klassen
Ereignisse
verwenden, um Informationen zu liefern.
Man sollte NIE von außen auf Controls eines Formulars
zugreifen.
| |
Morgen, danke für die Antwort. Bin gerade weiter am Experimentieren. Deine ganze Ausführung mag richtig sein und Schönheitstechnisch besser bzw. korrekter.
Aber eigentlich müsste mein Weg doch auch technisch korrekt sein?
Ich versuche mal so kurz wie möglioch zusammenzufassen:
Public Class Form1
enthält u.a. einen Open, Sende- und Closebutton und eine Textbox2
Public Class Class_COM
Enthält alles, was ich für die COM nutze.
(Stark abgespeckt)
Public Shared _serialPort As SerialPort
Public Function OpenCom() As Boolean '
' Schnittstelle öffnen
_serialPort = New SerialPort()
_serialPort.PortName = "COM5"
_serialPort.BaudRate = 115200
_serialPort.Parity = 0
_serialPort.DataBits = 8
_serialPort.StopBits = 1
_serialPort.RtsEnable = True
_serialPort.DtrEnable = True
_serialPort.Handshake = 0
_serialPort.ReadTimeout = 500
_serialPort.WriteTimeout = 500
_serialPort.Encoding = System.Text.Encoding.Default 'Standard ist
' ASCII 7-Bit
AddHandler _serialPort.DataReceived, AddressOf DataReceivedHandler
Try
_serialPort.Open()
Catch ex As Exception
MsgBox("Comport " & Form1.Comport & " konnte nicht geöffnet werden")
Return False
End Try
If _serialPort.IsOpen Then
Form1.TextBox2.Text = "open"
Return True
Else
Return False
End If
End Function
Public Sub WriteCom(message)
_serialPort.Write(message)
End Sub
Public Function CloseCom() As Boolean
_serialPort.Close()
Form1.TextBox2.Text = "closed"
Return True
End Function
Public Shared Sub DataReceivedHandler(sender As Object, e As _
SerialDataReceivedEventArgs)
Dim sp As SerialPort = CType(sender, SerialPort)
Dim indata As String = sp.ReadExisting()
Console.Write("RXX: ")
Console.WriteLine(indata)
Form1.TextBox2.Text = indata
End Sub
End Class Öffne ich von Form1 aus per Button die COM, erscheint die obige Message "open" erwartungsgemäß in der Textbox.
Dito bei Close. Klappt auch. Also ist die Interaktion der einen Klasse mit der Form1-Klasse möglich
Sende ich einen Text und er wird empfangen, dann wird das in der Debugausgabe gezeigt.
Dann soll er in die Textbox2 geschrieben werden.
Private Sub TextBox2_TextChanged(sender As System.Object, e As _
System.EventArgs) Handles TextBox2.TextChanged
Dim h As String
h = TextBox2.Text
End Sub Dort löst er das Ereignis "TextChanged" aus. Und der Text ist korrekt auslesbar. Als ist er angekommen.
Er steht in "h", wie man eindeutig sieht wenn man das Programm hier auf einen Breakpoint laufen lässt. Nur wird der nicht in der Box angezeigt. Da bleibt der letzte Text unverändert stehen.
Weder mit Refresh noch Update oder was sonst noch ich alles probiert habe.
Nochmal: 3 Funktionen aus der COM-Klasse senden Text. Bei 2en davon wird der Text von Form1 in der Textbox korrekt "upgedatet". Nur der empfangene Text aus der Empfangsfunktion kommt an, bleibt aber leer bzw. unsichtbar. Und löscht auch nicht den vorherigen Text an der Stelle in der Textbox2
Das ist das Phänomen, das ich nicht verstehe. | |
Re: Problem mit Aktualisierung einer Textbox bei seriellem Empfang | | | Autor: Lupus52 | Datum: 19.12.16 13:24 |
| Nachtrag: Habe deine Listings bezüglich der relevanten Zeilen eingebaut.
Dan bekam ich beim Versuch die Textbox zu beschreiben den Error.
"Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement TextBox2 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde."
Obwohl das ja im Thread Form1 steht. Aber ausgelöst eben durch den COM-Thread.
Weitere Forensuche brachte dann die Lösung per Invoke. Habe also das auch noch reingebastelt.
Erste Tests sind positiv! Jetzt muss ich mal mit echten Daten testen und nicht nur per Loop-Stecker.
Danke auf jeden Fall - ich bin einen riesigen Schritt weiter | |
Re: Problem mit Aktualisierung einer Textbox bei seriellem Empfang | | | Autor: Manfred X | Datum: 19.12.16 19:44 |
| Das ist korrekt.
Wenn die Com-Klasse in einem eigenen Thread ausgeführt wird,
kann der Zugriff auf Steuerelemente (sie laufen im UI-Thread)
nur per Invoke erfolgen. | |
Re: Problem mit Aktualisierung einer Textbox bei seriellem Empfang | | | Autor: Lupus52 | Datum: 19.12.16 20:05 |
| Ich danke dir - wenigstens dieser weitere Teil klappt jetzt auch. Es ist echt mühselig. | |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
vb@rchiv CD Vol.6 vb@rchiv Vol.6
Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
Online-Update-Funktion Entwickler-Vollversionen u.v.m.Jetzt zugreifen Tipp des Monats Neu! sevCoolbar 3.0
Professionelle Toolbars im modernen Design!
Mit sevCoolbar erstellen Sie in wenigen Minuten ansprechende und moderne Toolbars und passen diese optimal an das Layout Ihrer Anwendung an (inkl. große Symbolbibliothek) - für VB und MS-Access Weitere Infos
|