2015-10-09 1 views
0

Dans mon programme, j'ai un SwingWorker commençant un processus d'arrière-plan. Le flux d'erreurs du processus d'arrière-plan est redirigé vers stdout et le flux stdout est écrit (ligne par ligne) vers un JTextArea. Je pensais que je consommais le flux stdout avec ceJava - Processus de traitement (Builder) Sortie

BufferedReader processOut = new BufferedReader(
    new InputStreamReader(p.getInputStream())); 

Et ce à l'intérieur du doInBackground de SwingWorker:

String line; 
while((line = processOut.readLine()) != null) 
    process(line); 

Sur ma machine, le processus exécute à l'achèvement et le Zone texte est mis à jour périodiquement . Le processus se fige en arrière-plan sur d'autres ordinateurs cependant. J'ai augmenté la taille de la fenêtre par défaut command, donc c'est peut-être pourquoi je ne peux pas obtenir de processus pour geler sur mon ordinateur (c'est probablement très faux de plus que j'ai lu).

J'ai essayé de rediriger la sortie dans la commande ProcessBuilder avec > log.txt (je suis sous Windows 7 actuellement) mais je pense que ce qui a causé l'p.getInputStream() crash.

Comment puis-je le soit consommer stdout du sous-processus correctement dans ma classe SwingWorker, ou est-il possible de diriger la sortie vers un fichier et toujours obtenir la sortie print au JTextArea.

Edit:

I read here Qu'un flux d'entrée doit être lu rapidement à consommer. J'ai fourni la boucle qui traite le flux d'entrée ci-dessous. Je suppose que le tuyau ne reçoit pas plus de 4 Ko de données avant d'être lu, mais je ne peux rien supposer à ce stade.

while(processIsAlive()) 
    { 
     if(isCancelled()) 
     { 
      try 
      { 
       p.destroy(); 
       p.waitFor(); 
       return 1; 
      } 
      catch(Exception e){} 
     } 

     try 
     { 
      //Update Text Area 

      //get output from process 
      while((line = processOut.readLine()) != null) 
      { 
       //print output to text area 
       publish(line); 
      } 

      sleep(1000); 
     } 
     catch(Exception e){} 
    } 

EDIT 2:

Je pensais que ce que le processus redirigé vers un fichier, puis mettre un InputStream sur ce même fichier serait impossible, mais ce ne est pas écraser mon programme et l'interface graphique est encore mis à jour correctement. Je vais tester ça sur la machine problématique, je vais la marquer comme une réponse si ça marche.

Tout ce que je ne faisais redirect le processus dans un fichier:

pb.redirectOutput(new File("log.txt")); 

Et mettre le InputStream sur ce fichier au lieu du processus flux stdout.

processOut = new BufferedReader(new FileReader("log.txt")); 

Répondre

0

Lors du démarrage de processus, il est commode de lire le stdout et stderr dans un thread séparé chacun, parce que la lecture doit se faire par un appel à InputStream.read(), qui ne bloc le thread propriétaire.

Vous avez dit que votre processus d'arrière-plan redirigeait les erreurs vers stdout, d'accord. Ensuite, lisez uniquement la sortie standard, mais faites-le toujours dans un thread distinct, car le thread principal est bloqué dans l'appel waitFor jusqu'à la fin du processus. Mais le processus bloquera si son tampon de sortie est plein et que personne ne le lit.Dans ce cas, la différence entre votre environnement local (succès) et les autres (échec) pourrait être que, dans le vôtre, la quantité de données s'ajuste dans le tampon de sortie.

0

Ma deuxième modification fonctionnera sur n'importe quelle machine avec Java 7 ou plus tard. La lecture du flux d'entrée bloque, ce qui est incorrect pour une utilisation dans une interface graphique, mais les flux de processus sont lus de manière appropriée. Le problème réel avec la machine était que, pour une raison quelconque, le programme ne vidait pas correctement, donc j'ai ajouté fflush (stdout) au code source c dans le programme problématique, et cela a fonctionné parfaitement.