c# - Wartefunktion

OP #7839190

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?

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.

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)

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

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

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.

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.

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

Eine eigene Frage? Dieser Thread ist über ein Jahr alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.