Autor Beitrag
VampireSilence
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109
Erhaltene Danke: 5


C# (VS 2008 Express), PHP/MySQL, Windows XP
BeitragVerfasst: 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:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
            // some code

            DateTime wait = DateTime.Now.AddSeconds(30);

            while (DateTime.Now.Subtract(wait).TotalSeconds < 0)
            {
                Application.DoEvents();
            }

            // some code


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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: So 17.10.10 14:07 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109
Erhaltene Danke: 5


C# (VS 2008 Express), PHP/MySQL, Windows XP
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 17.10.10 15:27 
user profile iconVampireSilence hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109
Erhaltene Danke: 5


C# (VS 2008 Express), PHP/MySQL, Windows XP
BeitragVerfasst: 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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 :oops:):
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: So 17.10.10 16:08 
Genau :zustimm: . 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109
Erhaltene Danke: 5


C# (VS 2008 Express), PHP/MySQL, Windows XP
BeitragVerfasst: 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:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
anyFunction()
{
  // Code A
  result ErgebnisA = AsynchroneFunktion(Parameter);
  // Code B
  andereFunktion(ErgebnisA);
  // Code C
}


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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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...