Forum: PC-Programmierung c# - Wartefunktion


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Karl K. (leluno)


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?

von Εrnst B. (ernst)


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.

: Bearbeitet durch User
von Karl K. (leluno)


Lesenswert?

Εrnst B. schrieb:

danke für die Erklärung. So etwas wie globale Variablen, die in jeder 
Funktion gelten, gibt es nicht?

von Motopick (motopick)


Lesenswert?

Εrnst B. schrieb:

> System.Threading.Thread.Sleep(10);

Das koennte sogar noch auf einem Windows von Anno Dunnemals
funktionieren: Kooperatives Multitasking. :)

von Karl K. (leluno)


Lesenswert?

so scheint es zu gehen:
1
             dwntim=  100;
2
             //uint x = 0xffffffff;
3
                while (uart_str_rx[0] == 255 && sub_tim() >0) ;
4
5
...
6
             uint dwntim = 0;
7
             private uint sub_tim()
8
             {
9
                 Thread.Sleep(10);
10
                 return dwntim--;
11
             }

von Gunnar F. (gufi36)


Lesenswert?

sauber geht so was mit einem AutoReset-Event. Du startest einen Thread 
und wartest darin auf Freigabe des ARE. Diese erledigst du im 
ReceiveEventHandler, durch eine .Set()-Methode.

von Oliver R. (superberti)


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
}

: Bearbeitet durch User
von Ob S. (Firma: 1984now) (observer)


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.

von Karl K. (leluno)


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.

von Gunnar F. (gufi36)


Lesenswert?

aber while(); ist eine!

von Karl K. (leluno)


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.

von Oliver S. (oliverso)


Lesenswert?

Karl K. schrieb:
> Das macht das Programm inzwischen recht zuverlässig.

"Recht zuverlässig" ist bei Software eine Umschreibung für Murks.

Oliver

von Thorsten S. (thosch)


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.

: Bearbeitet durch User
von Gunnar F. (gufi36)


Lesenswert?

Karl K. schrieb:
> Endlosschleifen sind geradezu das Wesen der uc-Programmierung.

dann mach doch weiter so. Niemand will dir was aufzwingen.
Deine Frage bezog sich halt auf C# und nicht embedded C.
In C# IST while(); nunmal fast maximal blöd.

: Bearbeitet durch User
von Harald K. (kirnbichler)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.