Dynamisch Tasks erstellen anhand der Menge an Aufgaben

01/11/2018 23:17 Ludder231#1
Hi,

ich brauch einen Denkanstoß.

Und zwar lese ich von Webseiten bestimmte werte aus mit Regex. Jedoch ist die Anzahl der Seiten dynamisch. ca 100-2000 Seiten.

Ich lade immer den Quelltext runter und lese mit Regex die benötigten Daten aus.

Jetzt möchte ich, damit das schneller geht, mit Task asynchron machen.
Meine Frage ist: Wie kann ich das dynamisch aufteilen. Je mehr Seiten aufgerufen werden müssen, je mehr Task(bis zu einem maximum).

Würde mich über Ideen freuen. Danke :)
01/11/2018 23:51 Looneytune#2
Wieso C# wenn man Javascript nutzen kann? Schlagt auf mich ein, verklemmte Nerds.
01/12/2018 02:33 YatoDev#3
Quote:
Originally Posted by Ludder231 View Post
SNIP
Benutz die TaskFactory!!!

Alle tasks laufen da mit maximaler effektivität ab.

Code:
static void Main(string[] args)
        {
            TaskFactory factory = new TaskFactory(TaskCreationOptions.PreferFairness, TaskContinuationOptions.PreferFairness);
            List<Task> taskList = new List<Task>();

            for(int i = 0; i < 1000; i++)
            {
                taskList.Add(factory.StartNew(DoSomething));
            }

            Console.WriteLine("For loop finished");

            for(int i = 0; i < taskList.Count; i++)
            {
                try
                {
                    taskList[i].Wait();
                }
                catch
                {
                    // task already ended
                }

                Console.WriteLine("Task number: " + i + " finished");
            }

            Console.WriteLine("All tasks run");

            Console.ReadLine();
        }

        private static async void DoSomething()
        {
            Thread.Sleep(1000);
        }
EDIT:

Wenn du die CPU nicht überstrapazieren möchtest dann mach dein i/o synchron.
Wenn du nämlich die async methoden der jeweiligen i/o calls verwendest werden die anderen tasks anfangen zu laufen.

je nach anwendungsfall entscheiden

EDIT 2:

Wenn du den code oben ausführst kannst du beobachten wie die tasks ausgeführt werden.

Bei mir zb. werden 16 tasks gleichzeitig ausgeführt weil ich eben 8 kerne + hyperthreading habe.
Wenn du 4 kerne + hyperthreading hast werden sofern ressourcen frei sind 8 tasks gleichzeitig ausgeführt

EDIT 3:

UI updates bitte aber trotzdem asynchron machen sonst musst du auf den UI thread warten was wirklich keinen sinn macht

Quote:
Originally Posted by MC Überständer View Post
Wieso C# wenn man Javascript nutzen kann?
Sicher die Antwort die er haben wollte
01/12/2018 09:52 Serraniel#4
Task Parallel Library kümmert sich wie bereits erwähnt selber darum die Thread sinnvoll zu Organisieren.

MSDN gibt gerade 500er Fehler (Danke dafür @[Only registered and activated users can see links. Click Here To Register...] :rolleyes:) aber glaube aber die Artikel können dir später helfen (wenn es die richtigen sind, bekomme wie gesagt nen Internal Server Error zur Zeit):
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]

Quote:
Originally Posted by MC Überständer View Post
Wieso C# wenn man Javascript nutzen kann?
Wenn nichts sinnvolles zur Diskussion beitragen kannst, dann lass es auch bitte!
01/12/2018 11:23 Ludder231#5
Quote:
Originally Posted by YatoDev View Post
Benutz die TaskFactory!!!

Alle tasks laufen da mit maximaler effektivität ab.
Wenn ich das richtig sehe dann startet man einfach X Tasks die man in ner Liste speichert um den Status ab zugreifen und die arbeiten dann einfach die angegebenen Methode durch?

Quote:
Originally Posted by Serraniel View Post
Task Parallel Library kümmert sich wie bereits erwähnt selber darum die Thread sinnvoll zu Organisieren.

MSDN gibt gerade 500er Fehler (Danke dafür @[Only registered and activated users can see links. Click Here To Register...] :rolleyes:) aber glaube aber die Artikel können dir später helfen (wenn es die richtigen sind, bekomme wie gesagt nen Internal Server Error zur Zeit):
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]

Wenn nichts sinnvolles zur Diskussion beitragen kannst, dann lass es auch bitte!
Leider noch 500er Error. Ich sehe mir das an sobald das wieder funktioniert. Solange gucke ich mir den anderen Vorschlag an.
01/12/2018 12:23 Xio.#6
Einfacher:

[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]

Beide funktionen teilen die arbeit automatisch auf alle prozessorkerne auf und sind extrem simple zu implementieren ohne den alten code weg schmeissen zu muessen.

Quote:
Originally Posted by MC Überständer View Post
Wieso C# wenn man Javascript nutzen kann?
Wiso postet man sowas in der .NET section? JS ist rotz.

Quote:
Originally Posted by YatoDev View Post
Benutz die TaskFactory!!!

Alle tasks laufen da mit maximaler effektivität ab.

Code:
kinda bad code

Sicher die Antwort die er haben wollte
Dein Code ist ziemlich scheisse. Maximale effektivitaet? Nah :D
Quote:
Wenn du nämlich die async methoden der jeweiligen i/o calls verwendest werden die anderen tasks anfangen zu laufen.
???????????
Quote:
Wenn du die CPU nicht überstrapazieren möchtest dann mach dein i/o synchron.
I/O synchron zu machen ist nicht effektiver. I/O ist zu 99% warten. Da tut die CPU nichts. (tipp: das ist der grund warum man es async macht, dass man nicht wartet und nix tut)
01/12/2018 13:03 Ludder231#7
Quote:
Originally Posted by Xio. View Post
Einfacher:

[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]

Beide funktionen teilen die arbeit automatisch auf alle prozessorkerne auf und sind extrem simple zu implementieren ohne den alten code weg schmeissen zu muessen.
Der Code gefällt mir sehr gut. Von 22 Sekunden auf 9 Sekunden reduziert. Danke dir und natürlich auch den anderen.
01/12/2018 16:08 YatoDev#8
Quote:
Originally Posted by Xio. View Post
Einfacher:

[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]

Beide funktionen teilen die arbeit automatisch auf alle prozessorkerne auf und sind extrem simple zu implementieren ohne den alten code weg schmeissen zu muessen.
Dein Code ist ziemlich scheisse. Maximale effektivitaet? Nah :D

???????????

I/O synchron zu machen ist nicht effektiver. I/O ist zu 99% warten. Da tut die CPU nichts. (tipp: das ist der grund warum man es async macht, dass man nicht wartet und nix tut)
Woher nimmst du die information das der TE eine parallele for schleife möchte?
Er fragte nach etwas ThreadPool ähnlichem.

Außerdem ist die TaskFactory etwas allgemeiner. Du schmeißt einfach die methoden rein und irgendwann sind halt alle ausgeführt. Ist halt ein anderer anwendungsfall

Wenn du richtig lesen würdest dann hättest du verstanden warum es manchmal sinnvoller ist auf i/o zu warten. Es ist nicht immer sinnvoll tausende threads gleichzeitig abzuarbeiten. Das erfordert viel context switching.

und wenn du den code "scheiße" findest kannst du vielleicht auch zur community beitragen und erklären warum. Dein post war bisher nämlich unnötig.

EDIT: Okay wie sich herausgestellt hat war Foreach doch das richtige für ihn. Konnte man aber vorher nicht sagen
01/12/2018 17:29 th0rex#9
Quote:
Originally Posted by YatoDev View Post
Wenn du richtig lesen würdest dann hättest du verstanden warum es manchmal sinnvoller ist auf i/o zu warten. Es ist nicht immer sinnvoll tausende threads gleichzeitig abzuarbeiten. Das erfordert viel context switching.
lmao. Ja auf IO warten macht definitiv immer Sinn, generell lasse ich all meine Software andauernd warten, weil warten ist ja immer gut und so. Sowohl die TaskFactory als auch Parallel.ForEach spawnen keine Threads sondern Tasks. Wenn so nen Task auf IO warten muss, kommt in seine interne kontext struktur der Rest von dem Task rein (der ganze kram nach dem await wo du grade auf IO wartest) und der Task gibt dem Thread wieder die Kontrolle. Das ist zwar auch ein kontext switch, aber nicht zwischen user mode und OS. Der Thread auf dem dein Task läuft kann dann einfach einen anderen Task ausführen und sobald deine IO Resource da ist kann der Thread deinen suspendeten Task einfach wieder resumen. Ich meine man sieht doch wie gut diese Modell funktioniert, wenn du dir einfach mal die Performance von go oder C++/Rust mit ner vernünftigen coroutine lib + scheduler anguckst, das zerstört praktisch alles in benchmarks die viel IO machen, und die spawnen tausende bis hundert tausende Tasks.

Außerdem scheint Parallel.ForEach noch viel mehr zu machen als nur einfach dumm Tasks spawnen, so wie du es tust. Kannst dir ja mal die Antwort [Only registered and activated users can see links. Click Here To Register...] durchlesen.
01/12/2018 19:44 YatoDev#10
Tasks spawnen threads wenn das nötig ist. WIe soll das denn sonst funktionieren?
Das macht blos alles die runtime für dich.

Was klar sein sollte ist das der context switch zwischen tasks nicht so aufwendig ist wie bei OS threads.

Auch nochmal zur erinnerung: I/O muss nicht umbedingt zugriff auf eine datei sein.

Ich nehme mal an das du das mit kernel context switch meinst das wenn der auftrag abgeschlossen ist und der kernel wieder in den usermode zurückgibt. (da man mit der hardware über den kernel agiert)

Auch wenn du da vielleicht noch keinen anwendungsfall hattest es gibt genug fälle in denen man eine 100% auslastung der cpu vermeiden möchte.

EDIT: Damit hier nicht wieder sachen aus dem kontext gerissen werden: Natürlich ist es nicht der I/O zugriff der die cpu lasst produziert

Am besten kommt man da mit synchronem i/o zugriffen zurecht anstatt irgendwelche sleeps zu benutzen.

Ich habe nicht gesagt das man allgemein nur synchrone zugriffe auf irgendwelche resourcen machen soll.
01/12/2018 19:55 th0rex#11
Du hast gesagt, dass tausende threads zu nutzen kacke ist und ich wollte dich nur darauf hinweisen, dass da gar nicht tausende threads sondern tausende Tasks gespawnt werden.

Eine 100% Auslastung der CPU beim spawnen von Tasks zu vermeiden ist Aufgabe von dem Scheduler, und ich bin mir sicher, dass wenn du in .net Tasks spawnst und diese fertig sind die dazu gehörigen Threads nicht 100% der CPU verbrauchen. Auch wenn du auf IO wartest verbrauchst du nicht 100% der CPU, außer deine IO Implementierung ist ein riesen haufen Müll und pollt da andauernd was, anstatt einfach Events im Kernel zu registrieren.

Normal solltest du selber niemals einen Grund haben selber irgendwelche Sleeps einzubauen wenn du Tasks richtig benutzt, außer du willst halt wirklich mindestens X Sekunden warten.

Du sagst, dass man nicht nur synchrone Zugriffe machen soll, aber dir ist ja schon klar, dass synchrone Zugriffe den Thread blocken und alle anderen Tasks auf dem Thread somit auch und du genau deswegen niemals synchrone und asynchrone Zugriffe mischen solltest? Entweder machst du alles asynchron oder alles synchron oder du gehst 100% sicher, dass auf dem Thread wo die synchronen Sachen passieren nix asynchrones ist, was du mit den genannten Methoden ja nicht kannst.

Asynchrones und synchrones IO zu mischen macht genau so viel Sinn, wie in nem Task auf nen Mutex lock zu warten, der den Task nicht suspendet.
01/12/2018 22:56 YatoDev#12
Also um das mal zusammenzufassen behauptest du:

1.) Tasks können den CPU nicht zu 100% auslasten
2.) Wenn ich in einem Task ein Sleep einbaue blockiere ich die anderen Tasks

lul :D

Du stellst das ja hier da als ob ich das so machen würde:

await FileReadAsync()
FileRead()
await FileReadAsync()
FileRead()

xD
01/12/2018 23:53 Xio.#13
Quote:
Originally Posted by YatoDev View Post
Woher nimmst du die information das der TE eine parallele for schleife möchte?
Von da :)

Quote:
Originally Posted by Ludder231 View Post
Der Code gefällt mir sehr gut. Von 22 Sekunden auf 9 Sekunden reduziert. Danke dir und natürlich auch den anderen.
Wo hat er geschrieben dass er ne klasse will die unnoetig tasks erstellt? :P