| Autor |
Beitrag |
VampireSilence
      
Beiträge: 109
Erhaltene Danke: 5
C# (VS 2008 Express), PHP/MySQL, Windows XP
|
Verfasst: So 17.10.10 12:37
Teilweise habe ich das Problem, dass ich mein Programm warten lassen muss, um diverse asynchrone Funktionen zu "synchronisieren", zB wenn ich Daten aus dem Internet lade oder Ähnliches. Jetzt habe ich mir bisher immer mit der folgenden Prozedure geholfen:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| DateTime wait = DateTime.Now.AddSeconds(30);
while (DateTime.Now.Subtract(wait).TotalSeconds < 0) { Application.DoEvents(); }
|
Das Programm wartet zwar jetzt 30 Sekunden und es blockiert auch nicht, da ich ja jedes Mal Application.DoEvents() ausführe, aber es verbraucht in diese Moment 100% CPU und das stört mich. Mir war eigtl von vornherin klar, dass es nur eine Notlösung war und jetzt, wo sich der CPU-Verbrauch zu einem Problem entwicklet, wollte ich mal fragen: wie macht man sowas richtig ?
mfg
- VampireSilence
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 17.10.10 12:46
Du kannst das in Threads auslagern und dir von diesem (oder aus deinen asynchronen Fubnktionen) Bescheid sagen lassen, wenn die Bearbeitung abgeschlossen ist. So musst du nicht warten, sondern hast ein Event innerhalb dessen du dann weitermachen kannst. 
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: So 17.10.10 14:07
jaenicke hat folgendes geschrieben : | | oder aus deinen asynchronen Fubnktionen |
Eben. Wenn man schon einen asynchronen Vorgang zur Verfügung hat, muss es auch einen Weg ohne zusätzliche Threads oder Synchronisierung geben.
_________________ >λ=
|
|
VampireSilence 
      
Beiträge: 109
Erhaltene Danke: 5
C# (VS 2008 Express), PHP/MySQL, Windows XP
|
Verfasst: So 17.10.10 15:25
Ja, richtig. Bei "some code" steht noch einiges und da bestimmte Funktionen keine synchronen Varianten besitzen, ist das Auslagern keine gute Alternative. Damit wäre dann im Prinzip nichts gewonnen.
Teilweise füttere ich die while()-Condition auch nicht mit einer Zeitangaben, sondern einfach mit einer variablen, die vom asynchronen Prozess zu liefern ist, aber das macht für die CPU ja erstmal keinen Unterschied.
Das einzige, das ich noch kennen würde, wäre dann Thread.Sleep(), aber damit blockiert die Anwendung, was auch nicht gut wäre.
mfg
- VampireSilence
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 17.10.10 15:27
VampireSilence hat folgendes geschrieben : | | sondern einfach mit einer variablen, die vom asynchronen Prozess zu liefern ist |
Und genau an der Stelle kannst du auch ein Event auslösen oder Ähnliches. Damit sagst du also Bescheid, dass du fertig bist und reagierst dann darauf.
Wenn du das ganze ereignisorientiert umsetzt, entstehen solche Warteszenarien gar nicht erst.
|
|
VampireSilence 
      
Beiträge: 109
Erhaltene Danke: 5
C# (VS 2008 Express), PHP/MySQL, Windows XP
|
Verfasst: So 17.10.10 15:46
Ich glaube wir reden grade aneinander vorbei, also schreibe ich jetzt einfach mal das auf, wie ich dich verstehe. Also:
C#-Quelltext 1: 2: 3: 4:
| while (!AsynchronerProzessHatVariableÜbergeben) { Application.DoEvents(); } |
Und damit wären wir ja wieder bei 100% CPU, also wäre nichts gewonnen.
mfg
- VampireSilence
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 17.10.10 15:53
Nein, ganz ohne Schleife.
Mal Pseudocode (aus dem Kopf kann ich das in C# anders als in Delphi leider nicht in echtem Code  ):
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| Buttonclick: { BereiteBerechnungVor(); StarteAsynchroneBerechnung(); }
Asynchron: { Berechne(); InvokeEventAnHauptThread(); }
HauptThreadEvent: { ÜbernehmeDaten(); Messagedialog.Show("Fertig"); } |
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: So 17.10.10 16:08
Genau  . Falls man direkt die TPL einbeziehen will, wozu ich nur raten kann  , habe ich mal ein Minimal-Template dazu gepostet: c-sharp-forum.de/vie....php?p=602317#602317
_________________ >λ=
|
|
VampireSilence 
      
Beiträge: 109
Erhaltene Danke: 5
C# (VS 2008 Express), PHP/MySQL, Windows XP
|
Verfasst: So 17.10.10 19:14
@jaenicke
Ok, ich glaube zumindest weiss ich jetzt, wo unsere Differenz ist^^
In Zeile 16 Spuckt dein Ergebnis "Fertig" aus und ist damit beendet. Bei mir ist das aber nicht der Fall. Bei mir sieht es schematisch eher so aus:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| anyFunction() { result ErgebnisA = AsynchroneFunktion(Parameter); andereFunktion(ErgebnisA); } |
Oder kurz gesagt: meine asynchrone Funktion ist nicht das Ende. Danach geht es noch weiter. Und dieser weitere Code benötigt das Ergebnis der Funktion bereits und kann ohne diese nicht fortfahren. Er müsste also bei "Code B" pausieren und nach der Berechnung der AF (ich kürz das ma ab..) an der selben Stelle wieder fortfahren.
mfg
- VampireSilence
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 17.10.10 19:27
Genau so meine ich das ja. Wenn du vom asynchronen Aufruf oder Thread die Benachrichtigung mit dem Ergebnis bekommen hast, dann machst du darin weiter. Und rufst ggf. die nächste asynchrone Funktion auf.
Ereignisbasiert eben, genau wie Windows, .NET und C# insgesamt sind.
Du stellst dir das alles prozedural hintereinander vor. So wie es früher bei DOS war, immer eins nach dem anderen. So funktioniert das aber nicht gut, wie du ja selbst schon gemerkt hast...
// EDIT:
Ansonsten gibt es auch noch die Möglichkeit mit WaitForMultipleObjects zu warten um statt reinem Polling auch bei Nachrichten zu reagieren, damit die Anwendung noch reagiert.
Das ist aber die schlechtere Lösung...
|
|
|