Benutzereingaben und gleichzeitige Abarbeitung von Befehlen

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
Orioner
Beiträge: 102
Registriert: Mo Dez 10, 2012 10:52 am

Benutzereingaben und gleichzeitige Abarbeitung von Befehlen

Beitrag von Orioner » Do Sep 01, 2016 10:52 am

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?

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Benutzereingaben und gleichzeitige Abarbeitung von Befeh

Beitrag von Xin » Do Sep 01, 2016 3:15 pm

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.
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.

Orioner
Beiträge: 102
Registriert: Mo Dez 10, 2012 10:52 am

Re: Benutzereingaben und gleichzeitige Abarbeitung von Befeh

Beitrag von Orioner » Mi Sep 07, 2016 9:46 am

Es ging mir gerade um die nicht-thread-basierte Programmierung. Danke. Hast mir sehr geholfen.

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3123
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Benutzereingaben und gleichzeitige Abarbeitung von Befeh

Beitrag von cloidnerux » Mi Sep 07, 2016 10:17 pm

Dein Problem lässt sich mit einer Zustandmaschine lösen. Eine solche lässt sich mithilfe einer Zustandvariable, Schleife und switch realisieren:

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;
    }
}
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.
Redundanz macht wiederholen unnötig.
quod erat expectandum

mfro
Beiträge: 346
Registriert: Mi Jan 16, 2013 4:58 pm

Re: Benutzereingaben und gleichzeitige Abarbeitung von Befeh

Beitrag von mfro » Do Sep 08, 2016 10:01 am

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.
It's as simple as that. And remember, Beethoven wrote his first symphony in C.

Antworten