c# - Wartefunktion

OP #7839190
Lesenswert?

hallo,

brauche eine Wartefunktion:

1
downtimer_10ms = 100;
2
while (uart_str_rx[0] == 255 && downtimer_10ms>0) ;
3

4

5
...
6
 
7
      volatile public u16 downtimer_10ms = 0;
8
       private void timer2_Tick(object sender, EventArgs e)
9
       {
10
            if (downtimer_10ms > 0)
11
               downtimer_10ms--;
12
       }
13
....
14
timer2.Interval = 10; 
15
timer2.Start();

geht leider nicht. Was mache ich falsch?

#7839203
Lesenswert?

Solange du keine Threads verwendest, werden die Timer-Funktionen aus der Event-Loop heraus aufgerufen. Und wenn du bereits in einer anderen, aus der Event-Loop gestarteten Funktion bist, und nie in diese zurückkehrst, eben nie.

Nimm lieber ein System.Threading.Thread.Sleep(10);

Auch unschön, weil solange die GUI blockiert ist, aber funktioniert wenigstens... Trotzdem mieser Stil.

Edit: Das mit dem "funktioniert wenisgstens" relativiert sich, je nachdem wo du deinen uart_str_rx - Buffer befüllst. Wenn das auch als Event-Handler in der Main-Loop passiert, klappt es trotzdem nicht.

#7840551
Lesenswert?

In C# + GUI kann man blockierende Operationen mit async/await recht elegant lösen. Der Code mit dem Kommentar "Blockierende Aufrufe" läuft dann in einen eigenem Thread (mit all seinen Konsequenzen), das GUI wird aber dabei NICHT blockiert und sämtliche Events werden vom Dispatcher des GUI-Threads weiterhin abgearbeitet. Das kann ziemlich nützlich sein, wenn man z.B. mit einer MCU kommuniziert (typisches Frage->Antwort-Szenario).

Hier ein Beispiel:

1
System.Threading.CancellationTokenSource mCTS;
2

3
async private void BtStartLoop_Click(object sender, RoutedEventArgs e)
4
{
5
  try
6
  {
7
    mCTS = new System.Threading.CancellationTokenSource();
8
    await Task.Run(new Action(() =>
9
    {
10
      // Blockierende Aufrufe
11
      while (!mCTS.Token.IsCancellationRequested)
12
      {
13
      }
14
    }
15
      ), mCTS.Token);
16
  }
17
  catch (Exception Err)
18
  {
19
    // Fehlerbehandlung
20
  }
21
}
22

23
private void BtStopLoop_Click(object sender, RoutedEventArgs e)
24
{
25
  mCTS?.Cancel();
26
}
(Firma: 1984now) #7841648
Lesenswert?

Karl K. schrieb:

brauche eine Wartefunktion:

Nein. Was du wirklich brauchst, ist eine Ablösung dieses unsäglichen while-Polling durch eine ereignisorientierte Behandlung eingehender Daten.

Und dann wohl eine State-Machine, die die Ereignisse Timeout und Dateneingang sinnvoll behandelt.

Merke: an jeder Stelle deines Programms, an der du vermeinst, auf irgendetwas explizit warten zu müssen, hast du einen Fehler in der Struktur deines Programmes entdeckt. Gut geschriebene Programme brauchen niemals explizit auf irgendwas konkretes zu warten. Die reagieren immer nur auf Events. Und machen in der Zwischenzeit einfach garnix. Naja, sie "warten" halt auf eingehende Events. Aber das tun sie, ohne irgendwelche Rechenzeit sinnlos zu verbraten oder irgendwelche laufenden Threads sinnlos von der Ausführung zu supendieren.

OP #7842905
Lesenswert?

Ob S. schrieb:

Gut geschriebene Programme brauchen niemals explizit auf irgendwas konkretes zu warten. Die reagieren immer nur auf Events. Und machen in der Zwischenzeit einfach garnix. Naja, sie "warten" halt auf eingehende Events.

while (uart_str_rx[0] == 255 && sub_tim() >0);

Das event ist: uart_str_rx[0] hat einen Wert empfangen.

sub_tim() >0 ist keine Wartefunktion. Es stellt nur sicher, dass ein Abbruch erfolgt wenn - warum auch immer - der uart keinen Wert empfängt.

OP #7843088
Lesenswert?

Gunnar F. schrieb:

aber while(); ist eine!

Ob S. schrieb:

Gut geschriebene Programme brauchen niemals explizit auf irgendwas konkretes zu warten.

Wer bestimmt denn, was ein gut geschriebenes Programm ist? Jener höhere Programmierer, den wir verehren?

Ich habe einen AVR, der alle paar Minuten zuerst Messen und dann aufgrund der Messergebnisse etwas regeln soll. In der Zwischenzeit soll er nur die Zeit anzeigen. Das macht das Programm inzwischen recht zuverlässig. Beim uart muss halt irgendwie auf das Ende des Empfangs gewartet werden - erst danach kommt der nächste sinnvolle Programmschritt.

Endlosschleifen sind geradezu das Wesen der uc-Programmierung.

#7843104
Lesenswert?

Karl K. schrieb:

Endlosschleifen sind geradezu das Wesen der uc-Programmierung.

Aber nur von schlechter!

Streiche "Endlosschleifen", setze "Eventhandling" und "Statemachines", dann wird ein Schuh draus.

Ein gutes μC-Programm hat exakt eine Endlosschleife als Rahmen der Mainloop in main().

Außer ggf. bei der Initialisierung sollte man nirgendwo im Code auf irgendetwas warten.

Wie bereits von Anderen erwähnt: Wenn man irgendwo im Code auf etwas warten muß, hat man einen Strukturfehler gefunden.

Ausnahme wie gesagt, während der Initialisierung von Hardwarekomponenten.

#7843627
Lesenswert?

Karl K. schrieb:

uart_str_rx[0] hat einen Wert empfangen.

Das ist kein Event.

Gunnar F. schrieb:

aber while(); ist eine!

Und das ist keine Wartefunktion, sondern eine Endlosschleife.

Ein Event ist ein vom Betriebssystem verwaltetes Synchronisationsobjekt, auf das Threads mit entsprechenden Wartefunktionen warten können.

Die Win32-API (und auf der setzt auch das .Net-Geraffel auf) bietet dafür die Funktionen CreateEvent, SetEvent etc. und WaitForSingleObject bzw. WaitForMultipleObjects an.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren