2016-01-09 28 views
5

Ho un programma che attende una riga di input standard e quindi, dopo averlo elaborato (che richiede un tempo relativamente lungo), emette una risposta. Il programma prenderà input fino alla chiusura del flusso di input.Controllo di un processo interattivo utilizzando D

Come posso controllare quel programma da D? In altre parole, come potrei

  1. Assegnare al figlio una riga di input standard.
  2. Attendere che il processo figlio risponda.
  3. Ripetere, fino a quando non ho esaurito gli ingressi che voglio dargli.

Ho provato il seguente codice, ma non sorprendentemente, si attende il processo figlio per finire del tutto, e quindi stampa l'uscita tutto in una volta:

module main; 

import std.file; 
import std.path; 
import std.process; 
import std.stdio; 

void main(string[] args) 
{ 
    string[] inputs = ["test string 1", "test string 2"]; 

    auto pipes = pipeProcess(buildPath(getcwd(), "LittleTextProcessingApp"), Redirect.all); 
    scope(exit) wait(pipes.pid); 

    foreach(input; inputs) 
    { 
     pipes.stdin.writeln(input); 
    } 
    pipes.stdin.close; 

    foreach(line; pipes.stdout.byLine) 
    { 
     writeln(line); 
    } 
} 

Cioè, stampa, dopo un ritardo di un secondo,

Il seguente è stato dell'ingresso 500 ms fa: stringa di prova 1
Il seguente è stato dell'ingresso 500 ms fa: stringa di prova 2

Il comportamento desiderato è che esso stampa

Il seguente è stato dell'ingresso 500 ms fa: stringa di prova 1

dopo mezzo secondo, e la seconda linea di 500 ms dopo.

Il codice sorgente per il programma che sto testando il processo figlio è il seguente:

module main; 

import std.stdio; 
import core.thread; 

void main(string[] args) 
{ 
    foreach(input; stdin.byLine) 
    { 
     auto duration = 500.msecs; 
     stderr.writefln("Doing something for %s....", duration); 
     Thread.sleep(duration); 
     writefln("The following was input %s ago: %s", duration, input); 
    } 
} 

risposta

4

Il colpevole è il processo figlio. Dopo writefln, l'output non viene svuotato per impostazione predefinita. Invece, è tenuto in un buffer (alcuni kilobyte di lunghezza). Questa è una tecnica comune (non specifica di D) che può migliorare notevolmente la velocità quando, ad esempio, si scrive un file di grandi dimensioni su HDD in molti blocchi di pochi byte.

Per svuotare il buffer, utilizzare stdout.flush() ogni volta che si desidera che l'output venga visualizzato immediatamente. L'aggiunta di quella riga dopo l'ultimo writefln nel codice dell'esempio figlio corregge la situazione nell'esempio.

+0

Immagino di essere sicuro, dovrei usare stdout.flush() sia nel processo figlio che nel processo genitore. (Almeno questo era necessario per utilizzare il buffer di output interno in Xamarin, che è quello che stavo usando.) – AthanasiusOfAlex

+0

Ho notato che quando non si esegue direttamente in una shell D il buffer si riempie un po 'di tempo fino a quando non si sta scaricando. – weltensturm