Announcement

Collapse
No announcement yet.

Asynchrone Ausführung eines Delegats

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Asynchrone Ausführung eines Delegats

    In einem Programm sollen mehrere IP-Adressen angepingt werden, was ja ziemlich dauern kann, wenn die IPs offline sind. Also versuche ich eine asynchrone Ausführung mit Delegaten.

    [highlight=vbnet]
    Public Delegate Sub AskPing(ByVal IPAdresse As String, ByVal info As InfoDelegate)
    Public Delegate Sub InfoDelegate(ByVal IPAdresse As String, ByVal Antwort1 As String, ByVal Antwort2 As String)

    Public Class IPScanner
    Sub Main
    For i = 0 to 255
    IPAdresse = AufbauIPadresse(i)
    j += 1
    ScanAsk(IPAdresse, j)
    If j = 10 Then j = 0
    Next
    End Sub
    End Class[/highlight]

    Aufgerufen wird dann:
    [highlight=vbnet] Private Sub ScanAsk(ByVal IPAdresse As String, ByVal Lauf As Integer)
    Dim IPz As New IPZeugs
    Select Case Lauf
    Case 1
    Dim dgAntwort1 As New AskPing(AddressOf IPz.Anpingen)
    Dim dgInfo1 As New InfoDelegate(AddressOf ScanAnswer)
    dgAntwort1.Invoke(IPAdresse, dgInfo1)
    Case 2
    Dim dgAntwort2 As New AskPing(AddressOf IPz.Anpingen)
    Dim dgInfo2 As New InfoDelegate(AddressOf ScanAnswer)
    dgAntwort2.Invoke(IPAdresse, dgInfo2)
    '[...]
    Case 10
    Dim dgAntwort10 As New AskPing(AddressOf IPz.Anpingen)
    Dim dgInfo10 As New InfoDelegate(AddressOf ScanAnswer)
    dgAntwort10.Invoke(IPAdresse, dgInfo10)
    End Select

    End Sub

    Public Shared Sub ScanAnswer(ByVal IPAdresse As String, ByVal Antwort1 As String, ByVal Antwort2 As String)
    IPScanner.ListBoxIP.Items.Add(IPAdresse & " - " & Antwort1 & " - " & Antwort2)
    IPScanner.ListBoxIP.SelectedIndex = IPScanner.ListBoxIP.Items.Count - 1
    End Sub[/highlight]

    Dann gibt es noch die kleine Klasse IPZeugs
    [highlight=vbnet]Public Class IPZeugs

    Public Sub Anpingen(ByVal IPAdresse As String, ByVal info As InfoDelegate)
    Dim x As System.Net.IPHostEntry
    Dim siteResponds = My.Computer.Network.Ping(IPAdresse)
    Dim Antwort1 As String
    Dim Antwort2 As String

    If siteResponds Then
    Antwort1 = "online"
    Else
    Antwort1 = "offline"
    End If

    Antwort2 = ""
    Try
    x = System.Net.Dns.GetHostEntry(IPAdresse)

    Antwort2 = x.HostName
    Catch ex As Exception
    End Try

    info.Invoke(IPAdresse, Antwort1, Antwort2)
    End Sub

    End Class[/highlight]

    Dummerweise wartet das Programm aber bei jedem Aufruf dann doch auf das Pingergebnis, anstatt einfach weiterzulaufen und die nächste IP zu nehmen. Was mache ich falsch???
    Zuletzt editiert von GregorD; 06.12.2010, 15:42.

  • #2
    Was mache ich falsch???
    Keine Threads zu nutzen...
    Christian

    Comment


    • #3
      Worauf muß ich dann aber den neuen Thread adressieren?
      [highlight=vbnet]Case 1
      Dim dgAntwort1 As New AskPing(AddressOf IPz.Anpingen)
      Dim dgInfo1 As New InfoDelegate(AddressOf ScanAnswer2DB)
      Dim Antworter1 As New Thread(AddressOf dgAntwort1)[/highlight]
      Auf die Methode habe ich ja schon verwiesen. ?!?!?

      Comment


      • #4
        Worauf muß ich dann aber den neuen Thread adressieren?
        Es gibt eine globale Liste aller IP-Adressen, die gepingt werden sollen.
        Der Thread schaut in der Liste nach, ob Einträge vorhanden sind. Sind Einträge vorhanden nimmt sich der Thread einen Eintrag und löscht diesen aus der Liste. Dann pingt er die IP-Adresse an und schreibt das Ergebnis irgendwo hin.
        Ist kein Eintrag vorhanden beendet sich der Thread. Alternativ: Er wartet eine Zeit und schaut nochmal in der Liste nach. Falls die Liste zwischenzeitlich befüllt wird.

        Diesen Vorgang startest du mit X-Threads. Somit werden IP-Adresse zugleich angepingt.
        Christian

        Comment


        • #5
          Originally posted by Christian Marquardt View Post
          Es gibt eine globale Liste aller IP-Adressen, die gepingt werden sollen.
          Der Thread schaut in der Liste nach, ob Einträge vorhanden sind. Sind Einträge vorhanden nimmt sich der Thread einen Eintrag und löscht diesen aus der Liste. Dann pingt er die IP-Adresse an und schreibt das Ergebnis irgendwo hin.
          Ist kein Eintrag vorhanden beendet sich der Thread. Alternativ: Er wartet eine Zeit und schaut nochmal in der Liste nach. Falls die Liste zwischenzeitlich befüllt wird.

          Diesen Vorgang startest du mit X-Threads. Somit werden IP-Adresse zugleich angepingt.
          sowas ähnliches hatte ich ja mit meinem Select Case vor: er schnappt sich immer 10 IPadressen und baut reihum einen Thread auf, der dann irgendwann das Ergebnis zurückliefert. Deswegen bin ich ja auf die Geschichte mit den Delegates gekommen, damit der Aufruf unabhängig vom zurückgelieferten Ergebnis ist. Aber nun steh ich auf dem Schlauch. Muß ich denn den Aufruf gar nicht in ein Delegat packen, wenn ich es in einen neuen Thread gepackt habe?

          Konkret: wenn ich in meinem Case bin, würde es reichen, wenn ich einen neuen Thread aufbaue und die ganzen Delegat-Definitionen vergesse?

          Comment


          • #6
            Warum einfach, wenn es auch kompliziert geht. Warum 10er Päckchen? Warum eine unnötige Schleife?

            Würde da meinen Ansatz vorziehen
            Christian

            Comment


            • #7
              Originally posted by Christian Marquardt View Post
              Warum einfach, wenn es auch kompliziert geht. Warum 10er Päckchen? Warum eine unnötige Schleife?

              Würde da meinen Ansatz vorziehen
              Um den Rechner nicht zu überlasten, wenn der 255 Adressen gleichzeitig anpingt.

              Außerdem möchte ich einfach verstehen, worin mein Denkfehler liegt, selbst wenn es einen günstigeren Ansatz gibt.

              Also ganz generell (weil ich das eben lernen möchte): wenn ich eine Methode in einem neuen Thread aufrufe, möchte ich gerne eine Rückmeldung aus dem Thread bekommen und dann (quasi lokal) weiterverarbeiten. Also muß ich doch irgendwie das Threading mit dem Delegieren verkuppeln. Aber ich verstehe nicht, wie.

              Comment


              • #8
                Um den Rechner nicht zu überlasten, wenn der 255 Adressen gleichzeitig anpingt.
                Wo wäre der Unterschied in der Last, ob du das mit delegate oder Threads machst? Das ist unverständlich.

                Bei meinem Ansatz kannst du die Last durch die Anzahl der Threads steuern
                Christian

                Comment


                • #9
                  Originally posted by Christian Marquardt View Post
                  Wo wäre der Unterschied in der Last, ob du das mit delegate oder Threads machst? Das ist unverständlich.

                  Bei meinem Ansatz kannst du die Last durch die Anzahl der Threads steuern
                  Wie gesagt, es geht primär nicht mal um das Anpingen, sondern um das Lernen und Verstehen...

                  Comment


                  • #10
                    Okay, jetzt versuche ich es anders rum und mache entsprechend Threads auf:
                    [highlight=vbnet]
                    Select Case Lauf

                    Case 1
                    Dim Antworter1 As New Thread(AddressOf IPz.Anpingen)
                    Antworter1.Start(IPAdresse)
                    Case 2
                    Dim Antworter2 As New Thread(AddressOf IPz.Anpingen)
                    Antworter2.Start(IPAdresse)
                    Case 3
                    Dim Antworter3 As New Thread(AddressOf IPz.Anpingen)
                    Antworter3.Start(IPAdresse)
                    Case 4
                    Dim Antworter4 As New Thread(AddressOf IPz.Anpingen)
                    Antworter4.Start(IPAdresse)
                    Case 5
                    Dim Antworter5 As New Thread(AddressOf IPz.Anpingen)
                    Antworter5.Start(IPAdresse)
                    Case 6
                    Dim Antworter6 As New Thread(AddressOf IPz.Anpingen)
                    Antworter6.Start(IPAdresse)
                    Case 7
                    Dim Antworter7 As New Thread(AddressOf IPz.Anpingen)
                    Antworter7.Start(IPAdresse)
                    Case 8
                    Dim Antworter8 As New Thread(AddressOf IPz.Anpingen)
                    Antworter8.Start(IPAdresse)
                    Case 9
                    Dim Antworter9 As New Thread(AddressOf IPz.Anpingen)
                    Antworter9.Start(IPAdresse)
                    Case 10
                    Dim Antworter10 As New Thread(AddressOf IPz.Anpingen)
                    Antworter10.Start(IPAdresse)
                    [/highlight]
                    Dann ruft er im Thread aber doch ein Delegat auf, um eben die Rückmeldung zu geben.
                    [highlight=vbnet]
                    Public Sub Anpingen(ByVal IPAdresse As String)
                    Dim x As System.Net.IPHostEntry
                    Dim siteResponds = My.Computer.Network.Ping(IPAdresse)
                    Dim Antwort1 As String
                    Dim Antwort2 As String

                    If siteResponds Then
                    Antwort1 = "online"
                    Else
                    Antwort1 = "offline"
                    End If

                    Antwort2 = ""
                    Try
                    x = System.Net.Dns.GetHostEntry(IPAdresse)

                    Antwort2 = x.HostName
                    Catch ex As Exception
                    End Try

                    Dim info As New InfoDelegate(AddressOf IPScanner.ScanAnswer2DB)
                    info.Invoke(IPAdresse, Antwort1, Antwort2)
                    End Sub
                    [/highlight]
                    Dabei führt er scheinbar auch die Antwort-Methode aus, aber es erscheint nichts in der Listbox
                    [highlight=vbnet]
                    Public Shared Sub ScanAnswer2DB(ByVal IPAdresse As String, ByVal Antwort1 As String, ByVal Antwort2 As String)
                    IPScanner.ListBoxIP.Items.Add(IPAdresse & " - " & Antwort1 & " - " & Antwort2)
                    IPScanner.ListBoxIP.SelectedIndex = IPScanner.ListBoxIP.Items.Count - 1
                    End Sub
                    [/highlight]

                    Comment


                    • #11
                      Dein Problem ist aber ungeeignet um asynchrone Delegaten zu verstehen. Wobei ich asynchrone Delegaten im Zusammenhang mit den IAsyncResult bzw ISynchronizeInvoke Interface Patterns sehe(alle Möglichkeiten hier). Das macht aber (meine Meinung) nur wirklich Sinn wenn man 1 parallele Aufgabe hat und nicht n gleichartige Dinge tun will. Bei n gleichartigen Aufgaben eignen sich besser Threads und in diesem Fall (wenn du am Ping Beispiel festhalten willst) wäre dein Einstieg der ThreadPool. Dort kannst du festlegen das immer n Threads laufen wenn sie fertig sind werden sie in den Pool zurückgelegt und du kannst sie mit den nächsten IPs füttern und wieder starten.

                      Comment


                      • #12
                        Ich glaube du scheiterst an den ~speziellen~ VB Eigenheiten

                        Woher kennt die Klasse in der sich die Anpingen und ScanAnswer2DB Methoden befinden die IPScanner Form. Oder ist IPScanner einfach der Klassenname und keine Variable und du hoffst das VB die richtige Instanz der IPScanner Klasse findet?

                        Comment


                        • #13
                          Originally posted by Ralf Jansen View Post
                          Ich glaube du scheiterst an den ~speziellen~ VB Eigenheiten

                          Woher kennt die Klasse in der sich die Anpingen und ScanAnswer2DB Methoden befinden die IPScanner Form. Oder ist IPScanner einfach der Klassenname und keine Variable und du hoffst das VB die richtige Instanz der IPScanner Klasse findet?
                          IPScanner ist die Form, von der aus das ganze gestartet wird. in dieser befindet sich die ListboxIP. Und um zu der zurückzukommen, benutze ich ja eben ein Delegat. Also: irgendein Thread (der eine Adresse anpingt) soll die Methode ScanAnswer2DB aufrufen (die in der Form steht) und die dann das Ergebnis in die Listbox schreibt.

                          Ein Haltepunkt auf dieser Methode zeigt, daß sie von den vielen Threads auch aufgerufen wird und auch die Argumente mitgeliefert werden. Aber leider funktioniert der .Items.Add nicht; d.h. die Listbox bleibt leer.

                          Comment


                          • #14
                            IPScanner ist die Form
                            Ja, aber ist IPScanner ein Klassenname oder ein Instanzname?

                            Vielleicht wird das Problem das ich hier sehe mit etwas Code klarer. Im folgenden werden 2 Instanzen von IPScanner erzeugt und nur 1 angezeigt.
                            Jetzt manipuliere ich eine Form über den Klassennamen IPScanner. Auf welcher der beiden Instanzen form1 bzw. form2 wird denn nun die Manipulation vorgenommen. Die angezeigte form1 oder die nicht angezeigte form2?

                            Instanzdaten (wie zum beispiel Controls auf einer Form) sollten immer über eine konkrete Referenz auf eine Instanz geändert werden und niemals über den Klassennamen das führt nur zu Problemen und Missverständnissen.

                            [Highlight=VB.Net]Dim form1 As New IPScanner()
                            Dim form2 As New IPScanner()
                            form1.Show()

                            IPScanner.ListBoxIP.SelectedIndex = IPScanner.ListBoxIP.Items.Count - 1[/Highlight]

                            Daher solltest du, falls IPScanner wie von mir vermutet nur der Klassenname ist, den Klassen die eine Instanz von IPScanner benutzten auch eine Referenzen auf eine konkrete Instanz übergeben und nur über diese Referenzen mit der Instanz ~sprechen~.

                            Comment


                            • #15
                              Das klingt sehr einleuchtend und scheint mich in die richtige Richtung zu schubsen. Nun habe ich aber das Form nicht bewußt instanziert, sondern in dummer Heimwerkermentalität einfach eine Form genommen und sie so benannt. Wie weiß ich also, wie ich an die gerade aktive Instanz herankomme?

                              Comment

                              Working...
                              X