vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Brandneu! sevEingabe v3.0 - Das Eingabecontrol der Superlative!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

VB.NET - Fortgeschrittene
gleichzeitige Verarbeitung von Daten in mehreren Tasks 
Autor: Jojo
Datum: 06.09.18 11:34

Hallo,

ich kämpfe mit der Task.add Funktion und verstehe das wohl nicht richtig.

Hintergrund:
ich möchte zu mehreren tausend Bildern einen Hash Key erstellen.

Erwartete Funktion:
Solange wie MyTaskCounter<50 ist, solange sollen immer wieder neue Tasks gestartet werden, die die Aufgabe Set_ImageHash(DR) ausführen. Ist die Aufgabe erledigt, wird der Counter reduziert usw.

Dim MyTaskCounter As Integer = 0
 
'DT ist ein Object vom Typ DataTable und enthält alle Informationen über die 
' Bilder und gibt mehrere tausend Datensätze zurück
 
   For Each DR As DataRow In DT.Rows
      'Counter für das begrenzen der gleichzeitigen Tasks     
      Do Until MyTaskCounter < 50
         Application.DoEvents()
      Loop
 
      MyTaskCounter += 1
 
      Dim t As Task = Task.Run(Sub()
            Set_ImageHash(DR)
            MyTaskCounter -= 1
      End Sub)
      tasks.Add(t)
   Next
Die Funktion Set_ImageHash(DR) läd das Bild, ermittelt den Hash und schreibt den Hash in die Datenbank. Ein Rückgabewert ist nicht nötig, da das Ergebnis direkt in die Datenbank eingetragen wird.


Was mir nicht klar ist:
warum funktioniert das nicht so wie erwartet - egal auf welchem Wert MyTaskCounter steht - es dauert immer gleich lang und auch die CPU Last nimmt nicht zu. Ich vermute, dass immer nur ein Task verarbeitet wird und es nicht gleichzeitig läuft.

Was ist mein Fehler?

Joachim
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: gleichzeitige Verarbeitung von Daten in mehreren Tasks 
Autor: Franki
Datum: 08.09.18 03:46

Hallo Joachim

dir ist schon klar, dass unter Windows es nicht wirklich shneller sein kann wenn du Multi-Tasking verwendest, schon gar nicht wenn eine einzwlne Datenbank dahinter steht worin die Daten geschrieben werden sollen. Da wirst du keinen Gewinn an Geschwindigkeit erreichen, egal wie du das anstellsts.

Denn Tasks/Threads usw. sind zwar verteilte Sachen, aber das macht nur Sinn wenn es sich um unterschiedliche Aufgaben handelt.

Gruß
Frank
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: gleichzeitige Verarbeitung von Daten in mehreren Tasks 
Autor: Manfred X
Datum: 08.09.18 14:33

Hallo!

Du kannst Multitasking eventuell sinnvoll verwenden, wenn
Du die Task-Resultate zunächst im Haupspeicher sammelst
und sie nach Abschluß der Erledigung aller Tasks (Datensätze)
durch einen ADO-Zugriff in die Datenbank schreibst.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: gleichzeitige Verarbeitung von Daten in mehreren Tasks 
Autor: Jojo
Datum: 08.09.18 17:54

Ich dachte eigentlich nicht dass die Datenbank das Problem ist.

Die Funktion bekommt einen Datensatz. Dieser enthält Informationen über ein Bild, das irgendwo liegt. Das kann ein Lokaler Ort im Netzwerk sein oder (in 90%) eine Internet Adresse die per http oder FTP abgerufen wird.
Die Funktion holt sich das Bild als stream in ein Object. Das wird dann geprüft und nach bestimmten Regeln (weißen Rand abschneiden, bei bestimmten Formaten drehen usw.
Dann kommt die Funktion, die Das Thumbnail erstellt. Dabei wird das Bild auf 8x8 Pixel reduziert und in sw/Weiß umgewandelt. Das ganze wird dann der Hash.

Am Ende wird dann einfach nur der Hash in den datensatz eingetragen (der wird nicht offen gehalten oder so … ist ein update auf dem Primary Key).

Die Funktionen der Bildverarbeitung müssten deutlich mehr Rechenleistung verschlingen als das update auf die Datenbank … dennoch: Der Effekt ist da und es verändert sich

Ich habe es mal auf Async / Await geändert … jetzt verändert es sich etwas mehr … aber auch unbefriedigend

'...        
For Each DR As DataRow In DT.Rows
            Do Until MyTaskCounter < 100
                Application.DoEvents()
            Loop
 
            RunAsync(DR)
 
        Next
 
    End Sub
 
 
    Async Sub RunAsync(DR As DataRow)
 
        Try
            MyTaskCounter += 1
            Await Task.Run(Sub()
                               Set_ImageHash(DR)
                           End Sub)
        Catch ex As Exception
        End Try
        MyTaskCounter -= 1
    End Sub
Die Bewertung ist schwer, weil die Bilder sehr unterschiedlich groß sind. Hier mal ein paar Werte:

Bei 10 Tasks werden ca. 1 Bild pro sekunde verarbeitet
Bei 100 Tasks werden ca. 6 Bilder pro sekunde verarbeitet
Bei 500 Tasks werden ca. 10 Bilder pro sekunde verarbeitet cpu 30-35%

Ich vermute eher das Problem in der Internetverbindung … ich denke, dass die das ausbremst.

Joachim

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: gleichzeitige Verarbeitung von Daten in mehreren Tasks 
Autor: Manfred X
Datum: 09.09.18 13:19

Mein Tipp wäre:

Baue eine Klasse, die die erforderlichen
Daten aus der Datarow in Properties aufnimmt,
füge dieser Klasse alle Methoden hinzu, die für
die Erstellung des Hashtag erforderlich sind
und noch Readonly-Properties, durch die die Ergebnisse
abgefragt werden können.

Erstelle eine generische Liste, deren Elemente Instanzen
dieser Klasse sind und füge in dieser Liste für jede
Datarow/jedes Bild eine Instanz hinzu. Trage jeweils die
erforderlichen Daten aus der Table ein.

Übergibt jedem Thread beim parametrisierten Start ein
Element (= eine Referenz) aus dieser Liste.
Verwende für diese Threads den optimierten Threadpool.

Nach Beendigung des letzten Thread übertrage die Ergebnis-Daten
über einen einzelnen Zugriff in geeigneter Form in die Datenbank.

Auf diese Weise blockieren sich die Threads nicht und
werden optimal koordiniert ausgeführt.

Beitrag wurde zuletzt am 09.09.18 um 13:23:05 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: gleichzeitige Verarbeitung von Daten in mehreren Tasks 
Autor: Jojo
Datum: 09.09.18 20:17

Ja, das werde ich mal so probieren … danke schon mal an alle "creativen Mitdenker"

Joachim

Joachim

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: gleichzeitige Verarbeitung von Daten in mehreren Tasks 
Autor: Franki
Datum: 10.09.18 02:42

Hallo Joachim,

Zitat:

Ich dachte eigentlich nicht dass die Datenbank das Problem ist.

Die Funktion bekommt einen Datensatz. Dieser enthält
Informationen über ein Bild, das irgendwo liegt. Das kann ein
Lokaler Ort im Netzwerk sein oder (in 90%) eine Internet
Adresse die per http oder FTP abgerufen wird.


Aber das scheint mir der Flaschenhals zu sein, die Geschwindigkeit von einem lokalen Rechner zum Internet (egal ob http oder FTP oder sonst was) ist immer gefühlt zu langsam. Egal was du optimierst und was für Tests du machst, du solltes das immer mit lokalen Dateien machen. Nur dann kanst du Unterschiede zuverlässig messen und dich für die beste Variante entscheiden.

An der Zeit / Geschwindigkeit wie lange die Daten überhaupt brauchen kannst du nicht wirklich etwas ändern oder beeinflussen. Denn es hängt ja auch vom Server ab wie schnell der Daten liefern kann.

Du kannst nur die lokale Verarbeitung optimieren mehr nicht. Aber du mußt halt im Verhältnis schauen, ob diese Optimierung im Verhältnis zur Gesamtgeschwindigkeit überhaupt wichtig ist oder vielleicht auch nicht. 10 Millisekunden sparen bei einer Downloadzeit von x bringt im Endeffekt nicht wirklich etwas in der Gesamtbearbeitungszeit.

Gruß
Frank
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: gleichzeitige Verarbeitung von Daten in mehreren Tasks 
Autor: Jojo
Datum: 10.09.18 07:59

danke hierfür. ich werde mal die Ganzen punkte in einem neuen Projekt umsetzen. ich denke auch, dass ich einen getrennten Task brauche, der die Bilder runter lädt.

Joachim

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: gleichzeitige Verarbeitung von Daten in mehreren Tasks 
Autor: Manfred X
Datum: 10.09.18 08:44

Nein!
Die Download-Methode kannst Du in die von mir oben
angeregte Klasse integrieren. Es ist kein Problem,
bei "normaler" Bandbreite mehrere Dutzend Bild-Dateien
(vermutlich JPEGs) parallel im Multitasking (Pool) zu
laden.
Wenn Webseiten/Hoster dabei sind, die Bílder nur langsam laden,
stört das den Ladevorgang in anderen Tasks, die auf schnelle
Webseiten/Hoster zugreifen nicht.

Beitrag wurde zuletzt am 10.09.18 um 08:47:25 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: gleichzeitige Verarbeitung von Daten in mehreren Tasks 
Autor: Jojo
Datum: 10.09.18 09:17

Das sehe ich auch so. Die Idee zum download war aber die Messbarkeit. Da wäre es dann besser die vorab zu laden um die Vergleichbarkeit der Resultate zu gewährleisten...

Für den täglichen Einsatz ist der direkte Load in den stream sicherlich das bessere. Ist sehr viel Zeugs!

Über welche Methode würdest Du das laden? Ich holde die Bilder über Net.Webclient als Stream ohne den zwischen zu Speichern … ich denke das sollte die schnellste Methode sein ...

          Dim wc As New Net.WebClient()
                If DR("SourceUser") <> "" Then
                    wc.UseDefaultCredentials = True
                    wc.Credentials = New Net.NetworkCredential(DR( _
                      "SourceUser").ToString, DR("SourcePass").ToString)
                End If
                Using stream As New IO.MemoryStream(wc.DownloadData(DR( _
                  "SourceUrl").ToString))
 
                    originalBild = Image.FromStream(stream)
 
                End Using
 
'... verarbeite(originalBild)

Joachim

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: gleichzeitige Verarbeitung von Daten in mehreren Tasks 
Autor: Kuno60
Datum: 10.09.18 13:38

Der asynchrone Download von mehreren Bildern geht schneller als der synchrone Download der Bilder nacheinander, besonders wenn der Server etwas Zeit braucht, um die Bilder bereit zu stellen.
Wunder sollte man aber nicht erwarten.

Hier mal ein Beispiel zum asynchronen Download von 10 Bildern.
Wenn ein Bild geladen wurde, egal welches, kann es sofort verarbeitet werden.
Damit man weiß, welches Bild fertig geladen wurde, wird der Index des Bildes im Dictionary gespeichert.
(Die Uri kann man gut mit einem UriBuilder erstellen.)

    Dim SourceUrls(9) As Uri '10 Urls
    Dim PictureBoxen(9) As PictureBox '10 Pictureboxen
 
    Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles _
      Button1.Click
      Button1.Enabled = False
      Await LadeBilder() 'Download
      Button1.Enabled = True
    End Sub
 
    Private Async Function LadeBilder() As Task
      Try
        '----------------------------------------------------
        'Download definieren, mit Index
        Dim td As New Dictionary(Of Task(Of Byte()), Integer)
        For i = 0 To 9
          td.Add(New Net.Http.HttpClient().GetByteArrayAsync(SourceUrls(i)), i)
        Next
        Dim tl = td.Select(Function(x) x.Key).ToList 'Taskliste
        '----------------------------------------------------
        'Download ausführen
        While tl.Count > 0
          Dim tk = Await Task.WhenAny(tl) 'Task
          Dim ba = Await tk 'Bildbytes
          tl.Remove(tk)
          '... verarbeite (originalBild), Beispiel:
          Dim i = td(tk) 'Bildindex
          PictureBoxen(i).Image = Image.FromStream(New IO.MemoryStream(ba))
        End While
        '----------------------------------------------------
      Catch ex As Exception
        '...
      End Try
    End Function
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: gleichzeitige Verarbeitung von Daten in mehreren Tasks 
Autor: Jojo
Datum: 10.09.18 14:14

Danke, ist aber genau das was ich mache. Statt dem Array habe ich ein Datarow.

Da jede Funktion zum Umwandeln erst das Bild lädt und dann umwandelt, brauche ich den Rückgabe pointer nicht. Ich habe das nur zusammengefasst. Ich denke nicht das es viel bringt das zu trennen …

Bin Dank eurer Hilfe auf einem gutem Weg !!! Danke!

Joachim

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel