Tags: C Konsole Menü Echtzeit
Ich wollte eine kleine Konsolen-Anwendung schreiben, in der der Benutzer in einem Menü navigiert. Er bewegt hierzu mit den Pfeiltasten einen Cursor durch die verfügbaren Menü-Optionen und mit Enter, ruft er den entsprechenden Menüpunkt auf.
Das heißt, das Programm führt nur dann eine Aktion aus, nämlich den Wechsel von einem Menü zum anderen, wenn der Benutzer die entsprechenden Tasten drückt.
Jetzt soll im Hintergrund ein Timer laufen, nach dessen Ablauf das Programm eine Aktion/Berechnung o.ä. ausführt. Auf den ersten Blick scheint mir das Programm aber durch die Möglichkeit der Menüsteuerung nichts anderes tun zu können, als auf das Drücken der entsprechenden Navigationstasten des Benutzers zu warten: Entweder wartet das Programm auf eine Benutzereingabe oder der Timer läuft oder eine andere Aktion wird ausgeführt. Alles zusammen scheint mit den üblichen Kontrollstrukturen (Schleifen, Verzweigungen, etc.) nicht oder nicht ohne komplexere Algorithmen umgesetzt werden zu können.
Ich muss eine Echtzeit-Anwendung entwickeln, die zeitgleich auf Benutzereingaben reagiert. Ich vermute, es gibt Methoden dafür. Habt ihr dazu Ideen?
Ich könnte doch alle "Hintergrundoperationen" in einer Schleife laufen lassen und bei jedem Schleifendurchlauf abfragen, ob der Benutzer diese oder jene Taste gedrückt hat. Das ist mir soeben spontan eingefallen, bzw. kenne ich das Prinzip von der Programmierung von (Echtzeit-)Shooter-Spielen. Da wird nach diesem Prinzip verfahren. Wäre das eine Möglichkeit? Taugt diese Möglichkeit für jeden Anwendungsfall? Geht es eleganter?
Benutzereingaben und gleichzeitige Abarbeitung von Befehlen
- Xin
- nur zu Besuch hier
- Beiträge: 8862
- Registriert: Fr Jul 04, 2008 11:10 pm
- Wohnort: /home/xin
- Kontaktdaten:
Re: Benutzereingaben und gleichzeitige Abarbeitung von Befeh
Ich kenne das in der Regel so, dass man eine Anwendung schreibt, die auf Ereignisse wartet und daraufhin den Zustand der Anwendung ändert (z.B. Benutzer wählte Menüpunkt 1). Dafür kann man in eine Funktion springen, die tut, was Menüpunkt 1 tun soll oder man sieht die "Angewähltheit des Menüpunktes" wie eine Boolsche Variable: das laufende Programm fragt also ab, was es tun soll - aha, Menüpunkt 1 ist true.
Du kannst zum einen eine Schleife nutzen, die immer mal wieder fragt, ob der User was eingegeben hat.
Bei Multitasking-Betriebsystemen ist es aber eher üblich, dass man einen Thread öffnet, der auf Benutzereingaben wartet und darauf reagiert und einen, der im Hintergrund die Arbeit macht.
Ein Shooter wartet in der Regel nie, weil er laufend zeichnet (weil sich z.B. die Gegner bewegen). Die Maus kannst Du dennoch bewegen, weil das Zeichnen auch nur ein Subprozess ist. Auch wenn Du die 3D-Anwendung in z.B. GLUT programmierst, kommt der Moment, wo Du die Kontrolle an glut übergibst und Dein Programm nur noch gerufen wird, wenn das Kontrollprogramm (eben glut) Dich ruft. Du bist damit zum Hintergrundtask geworden.
Du kannst zum einen eine Schleife nutzen, die immer mal wieder fragt, ob der User was eingegeben hat.
Bei Multitasking-Betriebsystemen ist es aber eher üblich, dass man einen Thread öffnet, der auf Benutzereingaben wartet und darauf reagiert und einen, der im Hintergrund die Arbeit macht.
Ein Shooter wartet in der Regel nie, weil er laufend zeichnet (weil sich z.B. die Gegner bewegen). Die Maus kannst Du dennoch bewegen, weil das Zeichnen auch nur ein Subprozess ist. Auch wenn Du die 3D-Anwendung in z.B. GLUT programmierst, kommt der Moment, wo Du die Kontrolle an glut übergibst und Dein Programm nur noch gerufen wird, wenn das Kontrollprogramm (eben glut) Dich ruft. Du bist damit zum Hintergrundtask geworden.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
Re: Benutzereingaben und gleichzeitige Abarbeitung von Befeh
Es ging mir gerade um die nicht-thread-basierte Programmierung. Danke. Hast mir sehr geholfen.
- cloidnerux
- Moderator
- Beiträge: 3125
- Registriert: Fr Sep 26, 2008 4:37 pm
- Wohnort: Ram (Gibts wirklich)
Re: Benutzereingaben und gleichzeitige Abarbeitung von Befeh
Dein Problem lässt sich mit einer Zustandmaschine lösen. Eine solche lässt sich mithilfe einer Zustandvariable, Schleife und switch realisieren:
Nun musst du dafür eine Möglichkeit haben, den Zustand der Tasten ohne Blockierung abzurufen. Die Zustandsmaschine läuft ohne pause Durch, da aber ein Wechsel des Zustandes nur dann eintritt, wenn sich die Eingaben ändern, funktionieren auch Sequentielle Abläufe ohne blockierende Calls. Ein weiterer Vorteil: Du kannst das als Moore/Mealy Automat beschreiben. Mit etwas mehr Aufwand bekommt man auch die Zeit zwischen zwei Aufrufen konstant.
Code: Alles auswählen
enum STATES
{
IDLE,
STATE1,
STATE2
//[...]
}
//[....]
int state = IDLE;
while(1)
{
switch(state)
{
case IDLE:
if(keyDown == 1)
state = STATE1;
break;
case STATE1:
//[...]
break;
default:
state = IDLE;
}
}
Redundanz macht wiederholen unnötig.
quod erat expectandum
quod erat expectandum
Re: Benutzereingaben und gleichzeitige Abarbeitung von Befeh
Das kann man so machen (auf einem Microcontroller beispielsweise ist das mit die beste Vorgehensweise), auf einem PC mit mehreren GHz führt das busy-waiting allerdings u.U. ziemlich schnell dazu, das sämtliche Lüfter anspringen und sich das Ding nach Fön anhört, weil Du einen Kern voll mit der Abarbeitung des Zustandsautomaten auslastest (der dann wahrscheinlich viel schneller bzw. öfter abgearbeitet wird, als Du das brauchst).
Bei einer schnellen Maschine ist es u.U. besser, den Zustandsautomaten aus einem Timer aufzurufen.
Bei einer schnellen Maschine ist es u.U. besser, den Zustandsautomaten aus einem Timer aufzurufen.
It's as simple as that. And remember, Beethoven wrote his first symphony in C.