| |
VB.NET - Fortgeschrittenegleichzeitige 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 | |
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 | |
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. | |
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. | |
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 | |
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 | |
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 | |
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. | |
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 | |
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 | |
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 | |
| 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 TOP! Unser Nr. 1
Neu! sevDataGrid 3.0
Mehrspaltige Listen, mit oder ohne DB-Anbindung. Autom. Sortierung, Editieren von Spalteninhalten oder das interaktive Hinzufügen von Datenzeilen sind ebenso möglich wie das Erstellen eines Web-Reports. Weitere Infos
|