C# to VB.Net Eventhandling

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von ThuCommix.

    C# to VB.Net Eventhandling

    Haudi,

    hab gerade ein Problem, ein Kollege hat mir bei einer Klasse geholfen, nur leider ist diese in C# und da ich wenig erfahrung habe mit Eventhandling, verstehe ich nicht, wie ich diese in VB.Net übersetzt bekomme.

    C# - Code:
    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Diagnostics;
    4. using System.IO.Ports;
    5. using System.Threading;
    6. using System.Windows.Forms;
    7. {
    8. Public Class ComHelper
    9. {
    10. public delegate void DetectedComPortEventHandler(object sender, ComPortDetectedEventArgs e);
    11. public delegate void ProgressEventHandler(object sender, ComHelperProgressChangedEventArgs e);
    12. public event ComHelper.DetectedComPortEventHandler DetectedComPort;
    13. public event ComHelper.ProgressEventHandler ProgressChanged;
    14. public int Range
    15. {
    16. get;
    17. set;
    18. }
    19. Public ComHelper()
    20. {
    21. this.Range = 100;
    22. }
    23. public ComHelper(int range)
    24. {
    25. this.Range = range;
    26. }
    27. public void Run()
    28. {
    29. Thread thread = new Thread(new ThreadStart(this.InternalRun));
    30. thread.Start();
    31. }
    32. private void InternalRun()
    33. {
    34. List<ComPort> list = new List<ComPort>();
    35. for (int i = 0; i <= this.Range; i++)
    36. {
    37. try
    38. {
    39. SerialPort serialPort = new SerialPort("COM" + i.ToString());
    40. serialPort.Open();
    41. serialPort.Close();
    42. list.Add(new ComPort(i));
    43. }
    44. catch
    45. {
    46. Debug.WriteLine("No rabbit on COM" + i.ToString());
    47. }
    48. if (this.ProgressChanged != null)
    49. {
    50. int percentage = 100 * i / this.Range;
    51. ComHelperProgressChangedEventArgs comHelperProgressChangedEventArgs = new ComHelperProgressChangedEventArgs(percentage);
    52. Delegate[] invocationList = this.ProgressChanged.GetInvocationList();
    53. for (int j = 0; j < invocationList.Length; j++)
    54. {
    55. ComHelper.ProgressEventHandler progressEventHandler = (ComHelper.ProgressEventHandler)invocationList[j];
    56. if (progressEventHandler.Target is Control && ((Control)progressEventHandler.Target).InvokeRequired)
    57. {
    58. ((Control)progressEventHandler.Target).Invoke(progressEventHandler, new object[]
    59. {
    60. this,
    61. comHelperProgressChangedEventArgs
    62. });
    63. }
    64. else
    65. {
    66. progressEventHandler(this, comHelperProgressChangedEventArgs);
    67. }
    68. }
    69. }
    70. }
    71. if (this.DetectedComPort != null)
    72. {
    73. ComPortDetectedEventArgs comPortDetectedEventArgs = new ComPortDetectedEventArgs(list.ToArray());
    74. Delegate[] invocationList = this.DetectedComPort.GetInvocationList();
    75. for (int j = 0; j < invocationList.Length; j++)
    76. {
    77. ComHelper.DetectedComPortEventHandler detectedComPortEventHandler = (ComHelper.DetectedComPortEventHandler)invocationList[j];
    78. if (detectedComPortEventHandler.Target is Control && ((Control)detectedComPortEventHandler.Target).InvokeRequired)
    79. {
    80. ((Control)detectedComPortEventHandler.Target).Invoke(detectedComPortEventHandler, new object[]
    81. {
    82. this,
    83. comPortDetectedEventArgs
    84. });
    85. }
    86. else
    87. {
    88. detectedComPortEventHandler(this, comPortDetectedEventArgs);
    89. }
    90. }
    91. }
    92. }
    93. }
    94. }




    Meine bisherigen Versuche sehen so aus: (Problemstellen sind kommentiert)
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System
    2. Imports System.Collections.Generic
    3. Imports System.Diagnostics
    4. Imports System.IO.Ports
    5. Imports System.Threading
    6. Imports System.Windows.Forms
    7. Public Class ComHelper
    8. Public Delegate Sub DetectedComPortEventHandler(sender As Object, e As ComPortDetectedEventArgs)
    9. Public Delegate Sub ProgressEventHandler(sender As Object, e As ComHelperProgressChangedEventArgs)
    10. Public Event DetectedComPort As ComHelper.DetectedComPortEventHandler
    11. Public Event ProgressChanged As ComHelper.ProgressEventHandler
    12. Public Property Range() As Integer
    13. Public Sub New()
    14. Me.Range = 100
    15. End Sub
    16. Public Sub New(range As Integer)
    17. Me.Range = range
    18. End Sub
    19. Public Sub Run()
    20. Dim thread As New Thread(AddressOf Me.InternalRun)
    21. thread.Start()
    22. End Sub
    23. Private Sub InternalRun()
    24. Dim list As List(Of ComPort) = New List(Of ComPort)()
    25. For i As Integer = 0 To Me.Range
    26. Try
    27. Dim serialPort As SerialPort = New SerialPort("COM" + i.ToString())
    28. serialPort.Open()
    29. serialPort.Close()
    30. list.Add(New ComPort(i))
    31. Catch ex_45 As Exception
    32. Debug.WriteLine("No rabbit on COM" + i.ToString())
    33. End Try
    34. '#######################################
    35. ' Ab hier geht es los
    36. If Me.ProgressChanged IsNot Nothing Then
    37. Dim percentage As Integer = 100 * i / Me.Range
    38. Dim comHelperProgressChangedEventArgs As ComHelperProgressChangedEventArgs = New ComHelperProgressChangedEventArgs(percentage)
    39. Dim invocationList As [Delegate]() = Me.ProgressChanged.GetInvocationList()
    40. For j As Integer = 0 To invocationList.Length - 1
    41. Dim progressEventHandler As ComHelper.ProgressEventHandler = CType(invocationList(j), ComHelper.ProgressEventHandler)
    42. If TypeOf progressEventHandler.Target Is Control AndAlso (CType(progressEventHandler.Target, Control)).InvokeRequired Then
    43. (CType(progressEventHandler.Target, Control)).Invoke(progressEventHandler, New Object()() { Me, comHelperProgressChangedEventArgs })
    44. Else
    45. progressEventHandler(Me, comHelperProgressChangedEventArgs)
    46. End If
    47. Next
    48. End If
    49. 'Bis hierhin....
    50. 'Abfrage unten entprechend gleich
    51. '########################################
    52. Next
    53. If Me.DetectedComPort IsNot Nothing Then
    54. Dim comPortDetectedEventArgs As ComPortDetectedEventArgs = New ComPortDetectedEventArgs(list.ToArray)
    55. Dim invocationList As [Delegate]() = Me.DetectedComPort.GetInvocationList()
    56. For j As Integer = 0 To invocationList.Length - 1
    57. Dim detectedComPortEventHandler As ComHelper.DetectedComPortEventHandler = CType(invocationList(j), ComHelper.DetectedComPortEventHandler)
    58. If TypeOf detectedComPortEventHandler.Target Is Control AndAlso (CType(detectedComPortEventHandler.Target, Control)).InvokeRequired Then
    59. (CType(detectedComPortEventHandler.Target, Control)).Invoke(detectedComPortEventHandler, New Object()() { Me, comPortDetectedEventArgs })
    60. Else
    61. detectedComPortEventHandler(Me, comPortDetectedEventArgs)
    62. End If
    63. Next
    64. End If
    65. End Sub
    66. End Class




    Wäre wirklich cool wenn mir einer kurz helfen könnte und gegebenenfalls kurz erklären :)

    Dankeschön :)

    shaebich schrieb:

    Eventhandling
    geht inzwischen so:

    VB.NET-Quellcode

    1. Public Event MyEvent(sender As Object, e As EventArgs)
    2. Private Sub DoAnything()
    3. RaiseEvent MyEvent(Me, EventArgs.Empty)
    4. End Sub

    C#-Quellcode

    1. public EventHandler<EventArgs> MyEvent;
    2. private void DoAnything()
    3. {
    4. if(this.MyEvent != null)
    5. {
    6. this.MyEvent(this, EventArgs.Empty);
    7. }
    8. }

    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).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany Da fehlt aber das ​event-Schlüsselwort im C#-Code:

    C#-Quellcode

    1. ​public event EventHandler<EventArgs> MyEvent;
    2. private void DoAnything()
    3. {
    4. if(this.MyEvent != null)
    5. {
    6. this.MyEvent(this, EventArgs.Empty);
    7. }
    8. }
    Mit freundlichen Grüßen,
    Thunderbolt
    Der Ausgangs-Code ist kein korrektes c#, bitte kopiere wirklichen c#-Code ein.
    Ausserdem ist veraltet - glaub das meinte Rod - dass eigene Delegaten creiert werden - da nimmt man seit 2005 generische Delegaten.
    Daher braucht man den korrekten c#-Code, muss den bisserl aufarbeiten, und dann übersetzen.

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

    @ErfinderDesRades was meinst du mit wirklichen c# Code? Habe bisher noch nichts Delegates gebastelt, da alles mit Async und Await funktioniert hat.
    @RodFromGermany Danke. Den Grundgedanke von Event und wie man diese verwendet ist mir schon klar. Allerdings verstehe ich einfach nicht was der C# Code macht :D
    Wieso kann man ein Event auf Nothing prüfen? Und was macht der Rest von:
    Spoiler anzeigen

    C#-Quellcode

    1. if (this.ProgressChanged != null)
    2. {
    3. int percentage = 100 * i / this.Range;
    4. ComHelperProgressChangedEventArgs comHelperProgressChangedEventArgs = new ComHelperProgressChangedEventArgs(percentage);
    5. Delegate[] invocationList = this.ProgressChanged.GetInvocationList();
    6. for (int j = 0; j < invocationList.Length; j++)
    7. {
    8. ComHelper.ProgressEventHandler progressEventHandler = (ComHelper.ProgressEventHandler)invocationList[j];
    9. if (progressEventHandler.Target is Control && ((Control)progressEventHandler.Target).InvokeRequired)
    10. {
    11. ((Control)progressEventHandler.Target).Invoke(progressEventHandler, new object[]
    12. {
    13. this,
    14. comHelperProgressChangedEventArgs
    15. });
    16. }
    17. else
    18. {
    19. progressEventHandler(this, comHelperProgressChangedEventArgs);
    20. }
    21. }
    22. }


    schon Public Class kompiliert nicht, denn solch wird in c# klein geschrieben. Daher ist der Code, der gezeigt ist, nicht wirklich relevant.

    Was anne Events zu bemängeln ist, hat mit Async gar nix zu tun. Sondern - wie gesagt - mit den Events.
    Man könnte es leicht aufarbeiten, aber dazu musses erst mal in relevanter Form - also compilierbar - vorliegen.

    ErfinderDesRades schrieb:

    schon Public Class kompiliert nicht, denn solch wird in c# klein geschrieben. Daher ist der Code, der gezeigt ist, nicht wirklich relevant.


    Ok tut mir leid, keine ahnung wieso beim kopieren aus die 2 wörter groß geschrieben worden sind.

    Also hier die Class ComHelper
    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Diagnostics;
    4. using System.IO.Ports;
    5. using System.Linq;
    6. using System.Text;
    7. using System.Threading;
    8. using System.Threading.Tasks;
    9. using System.Windows.Forms;
    10. namespace WindowsFormsApplication1
    11. {
    12. public class ComHelper
    13. {
    14. public delegate void DetectedComPortEventHandler(object sender, ComPortDetectedEventArgs e);
    15. public delegate void ProgressEventHandler(object sender, ComHelperProgressChangedEventArgs e);
    16. public event ComHelper.DetectedComPortEventHandler DetectedComPort;
    17. public event ComHelper.ProgressEventHandler ProgressChanged;
    18. public int Range
    19. {
    20. get;
    21. set;
    22. }
    23. public ComHelper()
    24. {
    25. this.Range = 100;
    26. }
    27. public ComHelper(int range)
    28. {
    29. this.Range = range;
    30. }
    31. public void Run()
    32. {
    33. Thread thread = new Thread(new ThreadStart(this.InternalRun));
    34. thread.Start();
    35. }
    36. private void InternalRun()
    37. {
    38. List<ComPort> list = new List<ComPort>();
    39. for (int i = 0; i <= this.Range; i++)
    40. {
    41. try
    42. {
    43. SerialPort serialPort = new SerialPort("COM" + i.ToString());
    44. serialPort.Open();
    45. serialPort.Close();
    46. list.Add(new ComPort(i));
    47. }
    48. catch
    49. {
    50. Debug.WriteLine("No rabbit on COM" + i.ToString());
    51. }
    52. if (this.ProgressChanged != null)
    53. {
    54. int percentage = 100 * i / this.Range;
    55. ComHelperProgressChangedEventArgs comHelperProgressChangedEventArgs = new ComHelperProgressChangedEventArgs(percentage);
    56. Delegate[] invocationList = this.ProgressChanged.GetInvocationList();
    57. for (int j = 0; j < invocationList.Length; j++)
    58. {
    59. ComHelper.ProgressEventHandler progressEventHandler = (ComHelper.ProgressEventHandler)invocationList[j];
    60. if (progressEventHandler.Target is Control && ((Control)progressEventHandler.Target).InvokeRequired)
    61. {
    62. ((Control)progressEventHandler.Target).Invoke(progressEventHandler, new object[]
    63. {
    64. this,
    65. comHelperProgressChangedEventArgs
    66. });
    67. }
    68. else
    69. {
    70. progressEventHandler(this, comHelperProgressChangedEventArgs);
    71. }
    72. }
    73. }
    74. }
    75. if (this.DetectedComPort != null)
    76. {
    77. ComPortDetectedEventArgs comPortDetectedEventArgs = new ComPortDetectedEventArgs(list.ToArray());
    78. Delegate[] invocationList = this.DetectedComPort.GetInvocationList();
    79. for (int j = 0; j < invocationList.Length; j++)
    80. {
    81. ComHelper.DetectedComPortEventHandler detectedComPortEventHandler = (ComHelper.DetectedComPortEventHandler)invocationList[j];
    82. if (detectedComPortEventHandler.Target is Control && ((Control)detectedComPortEventHandler.Target).InvokeRequired)
    83. {
    84. ((Control)detectedComPortEventHandler.Target).Invoke(detectedComPortEventHandler, new object[]
    85. {
    86. this,
    87. comPortDetectedEventArgs
    88. });
    89. }
    90. else
    91. {
    92. detectedComPortEventHandler(this, comPortDetectedEventArgs);
    93. }
    94. }
    95. }
    96. }
    97. }
    98. }



    ComPort
    ComHelperProgressChangedEventArgs
    ComPortDetectedEventArgs
    sollten für die Problemstellung hier eigentlich irrelevant sein.
    also so sieht bislang meine c#-Überarbeitung aus. Ich verwende generische Event-Deklarationen, und wende eine einfachere Technik an, um die Events im Gui-Thread zu feuern:

    C#-Quellcode

    1. public class ComHelper {
    2. public event EventHandler<ComPortDetectedEventArgs> DetectedComPort;
    3. public event EventHandler<ComHelperProgressChangedEventArgs> ProgressChanged;
    4. public int Range {
    5. get;
    6. set;
    7. }
    8. public ComHelper() {
    9. this.Range = 100;
    10. }
    11. public ComHelper(int range) {
    12. this.Range = range;
    13. }
    14. public void Run() {
    15. Thread thread = new Thread(new ThreadStart(this.InternalRun));
    16. thread.Start();
    17. }
    18. private void InternalRun() {
    19. var list = new List<ComPort>();
    20. var ctl = Application.OpenForms[0];
    21. for (int i = 0; i <= this.Range; i++) {
    22. try {
    23. SerialPort serialPort = new SerialPort("COM" + i.ToString());
    24. serialPort.Open();
    25. serialPort.Close();
    26. list.Add(new ComPort(i));
    27. }
    28. catch {
    29. Debug.WriteLine("No rabbit on COM" + i.ToString());
    30. }
    31. if (this.ProgressChanged != null) {
    32. int percentage = 100 * i / this.Range;
    33. var comHelperProgressChangedEventArgs = new ComHelperProgressChangedEventArgs(percentage);
    34. ctl.BeginInvoke(ProgressChanged, this, comHelperProgressChangedEventArgs);
    35. }
    36. }
    37. if (this.DetectedComPort != null) {
    38. var comPortDetectedEventArgs = new ComPortDetectedEventArgs(list.ToArray());
    39. ctl.BeginInvoke(DetectedComPort, this, comPortDetectedEventArgs);
    40. }
    41. }
    42. }
    Aber ist das wirklich ein erwünschtes Verhalten, dass wann immer ein ProgressChanged gefeuert wird, dass gleichzeitig auch das ComportDetected - Event zu feuern ist?
    Eine andere Fragwürdigkeit scheint mir, dass für jeden Comport im Range ein ProgressChanged gefeuert wird - woher weiß der Empfänger nun, für welchen Comport es gilt?

    Und hier in vb:

    VB.NET-Quellcode

    1. Public Class ComHelper
    2. Public Event DetectedComPort As EventHandler(Of ComPortDetectedEventArgs)
    3. Public Event ProgressChanged As EventHandler(Of ComHelperProgressChangedEventArgs)
    4. Private _OnDetectedComPort As Action(Of ComPortDetectedEventArgs) = Sub(e) RaiseEvent DetectedComPort(Me, e)
    5. Private _OnProgressChanged As Action(Of ComHelperProgressChangedEventArgs) = Sub(e) RaiseEvent ProgressChanged(Me, e)
    6. Public Property Range() As Integer
    7. Public Sub New(Optional range As Integer = 100)
    8. Me.Range = range
    9. End Sub
    10. Public Sub Run()
    11. Dim thread As New Thread(New ThreadStart(AddressOf Me.InternalRun))
    12. thread.Start()
    13. End Sub
    14. Private Sub InternalRun()
    15. Dim list = New List(Of ComPort)()
    16. Dim ctl = Application.OpenForms(0)
    17. For i As Integer = 0 To Me.Range
    18. Try
    19. Dim serialPort As New SerialPort("COM" & i.ToString())
    20. serialPort.Open()
    21. serialPort.Close()
    22. list.Add(New ComPort(i))
    23. Catch
    24. Debug.WriteLine("No rabbit on COM" & i.ToString())
    25. End Try
    26. Dim comHelperProgressChangedEventArgs = New ComHelperProgressChangedEventArgs(100 * i \ Me.Range)
    27. ctl.BeginInvoke(_OnProgressChanged, comHelperProgressChangedEventArgs)
    28. Next
    29. Dim comPortDetectedEventArgs = New ComPortDetectedEventArgs(list.ToArray())
    30. ctl.BeginInvoke(_OnDetectedComPort, comPortDetectedEventArgs)
    31. End Sub
    32. End Class
    Bei Fragen fragen ;)

    (Und Ich hab auch eine Frage, nämlich obs funzt ;) ;) )

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    delegaten sind Referenzen auf Methoden und ein Event ist quasi eine Liste von delegaten, welche beim auftreten des Events aufgerufen werden. mit += new ... fügst du einem Event einen delegaten hinzu und mit -= entfernst du ihn entsprechend wieder. Wenn das Event-Objekt null/Nothing ist, ist dies gleichbedeutend damit, dass das Event von nirgends aus abonniert wurde, also du keinen delegaten hinzugefügt hast, dann kann auch kein delegate aufgerufen werden und du brauchst das Event auch nicht "raisen"
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    shaebich schrieb:

    kleines Sample Projekt
    mit kleinem Absturz bei Beendigung:

    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).
    Programmierfragen über PN / Konversation werden ignoriert!
    Nur noch zur Vollständigkeit @ErfinderDesRades
    und wende eine einfachere Technik an

    Deine Technik mag zwar funktionieren, ist aber suboptimal. Zu bevorzugen wäre die SynchronizationContext Klasse. Diese ist genau dafür gemacht und vermeidet solch Fehler wie oben.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    Mit SyncContext gäbe es halt eine andere Exception, aber das Problem löst das auch nicht.
    Und umständlicher und anfälliger zu bedienen ist er, weil birgt die Gefahr, im falschen Thread erstellt zu werden.

    Das Problem ist, dass der Thread läuft, und weiter das Gui aktualisieren will, auch wenn dieses schon geschlossen wurde.
    Mit meim Ansatz kann man das übrigens recht einfach abfangen - Control.IsDisposed abfragen.
    Mit SynchronisizeContext tut man sich da bischen schwerer und umständlicher.

    Hier habe ich übrigens den Ansatz ausgearbeitet, abgesichert und auf optimale Bedienfreundlichkeit fortentwickelt: codeproject.com/KB/vb/AsyncWorker2.aspx

    Kannste auch umstellen auf SyncContext, wenns beliebt - aber besser wird davon nix.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Vielleicht sollte der Thread einfach gebeten werden, sich durch Verlassen der Thread-Prozedur selbst zu beenden.
    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).
    Programmierfragen über PN / Konversation werden ignoriert!
    hatte aber extra im Form_Closing die Threads beendet.

    VB.NET-Quellcode

    1. Private Sub Form1_Closing(sender As Object, e As EventArgs) Handles Button2.Click, Me.FormClosing
    2. progressBarHelper.Abort()
    3. labelHelper1.Abort()
    4. labelHelper2.Abort()
    5. labelHelper3.Abort()
    6. labelHelper4.Abort()
    7. labelHelper5.Abort()
    8. labelHelper6.Abort()
    9. End Sub


    funktioniert bei mir auch ohne Probleme, vielleicht nicht die eleganteste Lösung, erfüllt allerding für die veranschaulichung des Projekts seinen Zweck :D

    ErfinderDesRades schrieb:

    Ausserdem ist veraltet - glaub das meinte Rod - dass eigene Delegaten creiert werden - da nimmt man seit 2005 generische Delegaten.


    Wow danke, daran hab ich gar nicht gedacht - Erspart eine Menge Arbeit.