List Of <Class>, vorherige Elemente werden überschrieben

  • VB.NET

Es gibt 32 Antworten in diesem Thema. Der letzte Beitrag () ist von Igel.

    Ich muss jetzt noch ganz blöd fragen:
    Wenn ich mir die Links zum Thema "wie programmiere ich richtig" ansehe, lese ich dauernd sinngemäß solche Sätze wie "in C# geht das auch nicht, mach das so wie es auch in C# geht.." usw. Man könnte den Eindruck bekommen, als sollte man von VB.net lieber gleich die Finger von lassen und das Ganze mit C# programmieren (dass man von VB die Finger lassen sollte, habe ich mittlerweile verstanden :D).
    Sicherlich war das nicht die Intension, allerdings frage ich mich (da zum jetztigen Zeitpunkt mein VB.net Kenntnisstand bei etwa 0 liegt), ob es sinnvoller wäre, zu C# umzusteigen (ich programmiere schon seit einigen Jahren mit C oder C-ähnlichen Sprachen (halt nicht objektorientiert), da ist VB.net schon eine Umstellung, vobei ich mich langsam daran gewöhne). Ich kam deshalb zu VB(.net), da ich zuvor schon mit VBA zu tun hatte.

    Was ist eure Meinung dazu? ich meine, ihr habt ja viel Ahnung von VB.net und programmiert ja auch damit, das wird ja auch seinen Grund haben..

    cya Igel
    Ob Du einen Vortrag in Deutsch oder Englisch hältst, bleibt Dir und Deinen Fähigkeiten überlassen. Grundsätzlich kannst Du alles genauso ausdrücken. Nur manche Sachen musst Du sprachlich bedingt anders formulieren. Aber vom sprachlichen Umfang kommt es (fast) auf's Gleiche raus.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    Ich muss auch jetzt noch viel mit VBA machen, weshalb mir beim permanenten Switch VB.Net einfacher fällt.

    Der Schritt von von C zu C# ist ähnlich gravierend wie der VBA zu VB.Net.
    Was jeweils bleibt, ist die Syntax.
    Die prozedurale Technik (obwohl sie bei beiden Sprachen noch möglich ist) muss aber aus dem Kopf und durch eine objektorientierte Denkweise ersetzt werden.

    Im übrigen ist VBA im Gegensatz zu C durchaus objektorientiert.
    Vor allem die dahinterliegenden Office-Objektmodelle, aber auch die Sprachelemente selbst.
    Allerdings kenne ich wenige Programmierer, die das tatsächlich auch nutzen.

    Was gegebenenfalls für C# spricht, ist die größere Verbreitung.
    Du findest im Internet mehr Beispiele.
    Und wenn du bei Großprojekten im Team programmierst, ist da meistens C# vorgeschrieben.
    Die meisten Schulen und Unis beginnen halt mit C-Syntax-basierenden Sprachen (C, Java, C++), weshalb der Sprung zu C# für die meisten Programmierer näherliegend ist.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Hallo nochmal,

    ich habe festgestellt, dass ich in eine Exception rein laufe (bei RaiseEvent MessageReceived(Me, ClientData.ReadLine), wenn der Client die Verbindung schließt: System.IO.IOException: "Von der Übertragungsverbindung können keine Daten gelesen werden: Eine vorhandene Verbindung wurde vom Remotehost geschlossen.

    Wie gehe ich mit sowas um?
    Sollte ich dann serverseitig die Verbindung schließen und neu öffnen oder gibt es einen anderen Weg? (falls das jetzt thematisch besser in einen neuen Post sollte, kann ich das auch machen, hier kennt man meinen Code halt schon 8-))

    cya Igel
    Zielgenaues Behandeln der Exception ist hier mal wieder das Stichwort. Wenn Du den Teil mit einem sinnvollen Try-Catch-Block einhüllst, dann ist alles gut.
    Du hast:

    VB.NET-Quellcode

    1. Private Sub Listening()
    2. '...
    3. Do Until IsActivated = False
    4. '...
    5. If ClientData IsNot Nothing Then
    6. Try
    7. RaiseEvent MessageReceived(Me, ClientData.ReadLine)
    8. Catch ex As Exception
    9. MsgBox(ex.Message)
    10. End Try
    11. End If
    12. '...
    13. Loop

    sinnvoller wäre da dann:

    VB.NET-Quellcode

    1. Private Sub Listening()
    2. '...
    3. Do While IsActivated
    4. '...
    5. Try
    6. RaiseEvent MessageReceived(Me, ClientData?.ReadLine)
    7. Catch IOEx As IO.IOException
    8. Exit Do
    9. Catch NREx As NullReferenceException
    10. Exit Do
    11. End Try
    12. '...
    13. Loop
    14. '...
    15. End Sub

    (Ich hab den If-Teil mal entfernt, geht sicherlich auch ohne, siehe ClientData?.ReadLine mit Null-Conditional-Operator)
    In den Catch-Teilen kannst Du dann auch ne gezielte Nachricht loggen, von wegen: "Der Client hat die Verbindung beendet". Danach ist ja eh für den Client Schluss. Wenn er wieder was will, muss er sich eben neu verbinden. Aber der Server sollte da nix dann mehr versuchen, da irgendwie wieder eine Verbindung herzustellen. Geht ja sicherlich eh nicht. Der Client wird schon gute Gründe haben, sich zu verabschieden. Und wenn bei der Clientseite ein Programm- oder PC-Absturz ist - na, dann kann der Server erst recht nix machen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    @ErfinderDesRades: war n bissle blöd ausgedrückt. Das Problem ist, dass ein php-Skript ja einmalig ausgeführt wird, d.h. nach dem Verbindungsaufbau und dem Senden und Empfangen der Nachrichten (was ja momentan überhaupt nicht funktioniert) sollte die Verbindung wieder geschlossen werden, da das Skript ja dann durch ist. D.h. wird das Skript erneut ausgeführt wird wieder eine Verbindung geöffnet und alles wiederholt sich. Da sich der Server "verschluckt" wenn die Verbindung Client-Seitig getrennt wird, dachte ich, dass man dann vielleicht den Server "resetten" muss, daher meinte ich schließen und neu öffnen. Aber deiner Antwort nach zu urteilen, muss der Server einfach nur auf die nächste eingehende Verbindung warten oder?

    @VaporiZed: hab mal deine Empfehlung eingebaut, hier nun mein aktueller Listener:

    VB.NET-Quellcode

    1. Private Sub TCPListening(Optional ByVal SilentMode As Boolean = True)
    2. ' CREATE LISTENER LOOP
    3. Do Until IsActivated = False
    4. ' ACCEPT INCOMING CONNECTIONS
    5. If TCPServer.Pending = True Then
    6. Client = TCPServer.AcceptTcpClient
    7. ClientData = New StreamReader(Client.GetStream)
    8. End If
    9. ' RAISE EVENT FOR INCOMING MESSAGES
    10. Do While IsActivated
    11. Try
    12. RaiseEvent MessageReceived(Me, ClientData?.ReadLine)
    13. Catch IOEx As IO.IOException
    14. Console.WriteLine(IOEx.Message)
    15. Exit Do
    16. Catch NREx As NullReferenceException
    17. Console.WriteLine(NREx.Message)
    18. Exit Do
    19. End Try
    20. Loop
    21. ' REDUCE CPU USAGE
    22. Thread.Sleep(100)
    23. Loop
    24. End Sub


    Ist das TCPServer.Pending eigentlich überhaupt notwendig?

    VB.NET-Quellcode

    1. ' ACCEPT INCOMING CONNECTIONS
    2. If TCPServer.Pending = True Then
    3. Client = TCPServer.AcceptTcpClient
    4. ClientData = New StreamReader(Client.GetStream)
    5. End If


    thx, Igel

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Igel“ ()

    So, nachdem ich meine Klasse für die TCP-Kommunikation umgebaut habe (ich habe im Internet nen C#-Code gefunden), funktioniert sie nun.
    Jetzt möchte ich noch die Möglichkeit haben, das Threading zu stopppen, wenn der Benutzer die externe Kommunikation nicht haben will.

    So sieht der Code jetzt aus (Code im Hauptprogramm hat sich nicht geändert):

    VB.NET-Quellcode

    1. Option Strict On
    2. 'Imports System.IO
    3. Imports System.Net
    4. Imports System.Net.Sockets
    5. Imports System.Text
    6. Imports System.Threading
    7. Public Class TCPControl
    8. Public Event MessageReceived(sender As TCPControl, Data As String)
    9. Private ServerIP As IPAddress
    10. Private TCPServer As TcpListener
    11. Private TCPCommThread As Thread
    12. Private IsActivated As Boolean = True
    13. Private Response As String = ""
    14. Public Sub New(IP As String, Port As Integer)
    15. ServerIP = IPAddress.Parse(IP)
    16. TCPServer = New TcpListener(ServerIP, Port)
    17. End Sub
    18. Public Sub StartServer()
    19. IsActivated = True
    20. If TCPCommThread Is Nothing Then
    21. TCPCommThread = New Thread(Sub() TCPListening()) With {.IsBackground = True}
    22. TCPCommThread.Start()
    23. End If
    24. End Sub
    25. Public Sub StopServer()
    26. IsActivated = False
    27. If TCPCommThread IsNot Nothing AndAlso TCPCommThread.IsAlive Then
    28. TCPCommThread.Abort()
    29. TCPCommThread = Nothing
    30. End If
    31. End Sub
    32. Public Function ServerStatus() As Boolean
    33. Return IsActivated
    34. End Function
    35. Private Sub TCPListening(Optional ByVal SilentMode As Boolean = True)
    36. If IsActivated = True Then
    37. Try
    38. TCPServer.Start()
    39. Console.WriteLine("The server is running at port 4305.")
    40. Console.WriteLine("The local End point is: " & TCPServer.LocalEndpoint.ToString)
    41. Console.WriteLine("Waiting for a connection..")
    42. While IsActivated
    43. Dim TCPsocket As Socket = TCPServer.AcceptSocket()
    44. Console.WriteLine("Connection accepted from " & TCPsocket.RemoteEndPoint.ToString)
    45. Dim b As Byte() = New Byte(99) {}
    46. Dim k As Integer = TCPsocket.Receive(b)
    47. Dim TCPRequest As String = Encoding.ASCII.GetString(b.Take(k).ToArray())
    48. Console.WriteLine("Recieved: " & TCPRequest)
    49. RaiseEvent MessageReceived(Me, TCPRequest)
    50. If Response <> "" Then
    51. Dim asen As ASCIIEncoding = New ASCIIEncoding()
    52. TCPsocket.Send(asen.GetBytes(Response))
    53. TCPsocket.Close()
    54. Console.WriteLine("Sent: " & Response)
    55. Response = ""
    56. End If
    57. Thread.Sleep(100)
    58. End While
    59. TCPServer.[Stop]()
    60. Catch ex As Exception
    61. Console.WriteLine("Error: " & ex.StackTrace)
    62. End Try
    63. End If
    64. End Sub
    65. Public Sub SendToClient(ByVal text As String)
    66. If IsActivated = True Then
    67. Response = text
    68. End If
    69. End Sub
    70. End Class


    Zunächst mal vorab: ich weiß, dass Thread.Abort() eine Exception wirft und denn Code dann irgendwo beenden will (was mir egal wäre, weil ich dann keine Daten mehr verarbeiten will).

    Mein Problem ist nun, dass wenn ich den Server stoppe, das Programm so lange hängt, bis nochmal eine Nachricht an den Server gesendet wird. Das soll natürlich nicht passieren.

    Weiß hier von euch jemand, warum das so ist und wie ich das hin bekomme, dass der Thread einfach geschlossen wird, sodass die Kommunikation unterbunden wird?

    cya Igel

    Igel schrieb:

    VB.NET-Quellcode

    1. While IsActivated
    Arbeite mit dem Abbruch-Flag IsActivated.
    Wenn es gelöscht ist, verlasse diese Schleife und feddich, teste das Flag jeweils vor und nach dem Senden.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    VB-Fragen über PN / Konversation werden ignoriert!
    *Vollzitat entfernt*

    Bei mir ist das Empfangen das Problem (genauer gesagt das Dim TCPsocket As Socket = TCPServer.AcceptSocket()), aber durch deinen Post bin ich auf die Idee gekommen das TCPserver.Pending() zu verwenden, jetzt klappt es ^^, danke also für den Hinweis :thumbsup:

    Das Ganze sieht jetzt so aus:

    VB.NET-Quellcode

    1. Option Strict On
    2. 'Imports System.IO
    3. Imports System.Net
    4. Imports System.Net.Sockets
    5. Imports System.Text
    6. Imports System.Threading
    7. Public Class TCPControl
    8. Public Event MessageReceived(sender As TCPControl, Data As String)
    9. Private ServerIP As IPAddress
    10. Private ServerPort As Integer
    11. Private TCPServer As TcpListener
    12. Private TCPCommThread As Thread
    13. Private IsActivated As Boolean = True
    14. Private Response As String = ""
    15. Public Sub New(IP As String, Port As Integer)
    16. ServerIP = IPAddress.Parse(IP)
    17. ServerPort = Port
    18. End Sub
    19. Public Sub StartServer()
    20. IsActivated = True
    21. TCPServer = New TcpListener(ServerIP, ServerPort)
    22. If TCPCommThread Is Nothing Then
    23. TCPCommThread = New Thread(Sub() TCPListening()) With {.IsBackground = True}
    24. TCPCommThread.Start()
    25. End If
    26. End Sub
    27. Public Sub StopServer()
    28. IsActivated = False
    29. If TCPCommThread IsNot Nothing AndAlso TCPCommThread.IsAlive Then
    30. TCPServer = Nothing
    31. TCPCommThread.Abort()
    32. TCPCommThread = Nothing
    33. End If
    34. End Sub
    35. Public Function ServerStatus() As Boolean
    36. Return IsActivated
    37. End Function
    38. Private Sub TCPListening(Optional ByVal SilentMode As Boolean = True)
    39. 'Console.WriteLine("IsActivated: " & IsActivated)
    40. If IsActivated = True Then
    41. Try
    42. TCPServer.Start()
    43. Console.WriteLine("The server is running at port 4305.")
    44. Console.WriteLine("The local End point is: " & TCPServer.LocalEndpoint.ToString)
    45. Console.WriteLine("Waiting for a connection..")
    46. While IsActivated
    47. If TCPServer.Pending Then
    48. Dim TCPsocket As Socket = TCPServer.AcceptSocket()
    49. Console.WriteLine("Connection accepted from " & TCPsocket.RemoteEndPoint.ToString)
    50. Dim b As Byte() = New Byte(99) {}
    51. Dim k As Integer = TCPsocket.Receive(b)
    52. Dim TCPRequest As String = Encoding.ASCII.GetString(b.Take(k).ToArray())
    53. Console.WriteLine("Recieved: " & TCPRequest)
    54. RaiseEvent MessageReceived(Me, TCPRequest)
    55. If Response <> "" Then
    56. Dim asen As ASCIIEncoding = New ASCIIEncoding()
    57. TCPsocket.Send(asen.GetBytes(Response))
    58. TCPsocket.Close()
    59. Console.WriteLine("Sent: " & Response)
    60. Response = ""
    61. End If
    62. End If
    63. Thread.Sleep(100)
    64. End While
    65. TCPServer.[Stop]()
    66. Catch ex As Exception
    67. Console.WriteLine("Error: " & ex.StackTrace)
    68. End Try
    69. End If
    70. End Sub
    71. Public Sub SendToClient(ByVal text As String)
    72. If IsActivated = True Then
    73. Response = text
    74. End If
    75. End Sub
    76. End Class

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Hallo nochmal,

    ich habe noch ne Frage zu der XML-Geschichte: Gibt es eine Möglichkeit, auch Variablen vom Typ Private zu serialisieren?

    Bevor jetzt jemand fragt, warum ich sowas will, hier schon mal die Erklärung ;) :
    Ich habe eine Integer-Variable, die als so ne Art PRIMARY KEY (wie bei Datenbanken) arbeitet. Sie soll nicht manuell veränderbar sein, sondern nur durch ein Sub, das die Variable um eins erhöht.

    So sieht die Klasse aktuell aus:

    VB.NET-Quellcode

    1. <Serializable()>
    2. Public Class SettingsInfo
    3. Public AllowRemoteControl As Boolean
    4. Public RemotePort As Integer
    5. Public AutoRestartServer As Boolean
    6. Public SteamCmdPath As String
    7. Public AppID As Integer
    8. Public DailyServerRestart As Boolean
    9. Public DailyRestartTime As String
    10. Public DailyRestartStopAllServers As Boolean
    11. Public DiscordSupportEnabled As Boolean
    12. Public DiscordBotName As String
    13. Public DiscordSupportURL As String
    14. Public WebserverUsername As String
    15. Private MaxServerID As Integer
    16. Public ReadOnly Property GetNewServerID() As Integer
    17. Get
    18. Return MaxServerID + 1
    19. End Get
    20. End Property
    21. Public Sub IncMaxServerID()
    22. MaxServerID = MaxServerID + 1
    23. End Sub
    24. End Class

    Die Variable MaxServerID wird aber nicht in der XML-Datei gespeichert, solange sie Private ist.

    Gibts hier ne Möglichkeit, die dennoch mitzunehmen?

    Thx!

    cya Igel

    Igel schrieb:

    Sie soll nicht manuell veränderbar sein
    Mach da ne Property draus mit nem Public Getter und nem Private Setter:

    VB.NET-Quellcode

    1. Dim _MyValue As Integer
    2. Public Property MyValue As Integer
    3. Get
    4. Return _MyValue
    5. End Get
    6. Private Set(value As Integer)
    7. _MyValue = value
    8. End Set
    9. End Property
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    VB-Fragen über PN / Konversation werden ignoriert!