2009-11-15 7 views
3

La principale forme dans mon application lance un nouveau fil, et ouvre alors une autre forme, qui sert de fenêtre de progression. Le thread achemine des données entre deux applications de console et les informations de l'erreur StandardError sont envoyées à la fenêtre de progression. J'utilise DataReceivedEventHandler pour lire l'erreur standard de manière asynchrone.C# problème avec redirection erreur standard

Si je laisse tout son cours, il fonctionne parfaitement bien, mais un problème se pose lorsqu'un utilisateur appuie sur le bouton « annuler » sur mon formulaire. Que se passe-t-il, les fonctions ErrorDataReceived continuer à tirer même après que j'arrête les processus! Parfois, l'annulation fonctionnera avec succès, mais parfois je reçois une condition de blocage (je pense que c'est le bon mot).

Voici quelques extraits de mon code afin que vous puissiez voir ce qui se passe. Il se bloque en attente sur "p2.WaitForExit();" et "Invoke (new updateProgressDelegate (this.updateProgress), e.Data);" (studio visuel met une flèche verte par ces lignes, et dit qu'ils seront le prochain à exécuter)

// start 2 processes (p & p2) and pipe data from one to the other 
// this runs in thread t 
        p.Start(); 
        p2.Start(); 
        byte[] buf = new byte[BUFSIZE]; 
        int read = 0; 
        p2.ErrorDataReceived += new DataReceivedEventHandler(p2_ErrorDataReceived); 
        p2.BeginErrorReadLine(); 

        try 
        { 
         read = p.StandardOutput.BaseStream.Read(buf, 0, BUFSIZE); 
         while (read > 0 && read <= BUFSIZE) 
         { 
          if (canceled==false) 
           p2.StandardInput.BaseStream.Write(buf, 0, read); 
          if (canceled==false) 
           read = p.StandardOutput.BaseStream.Read(buf, 0, BUFSIZE); 
          else 
          { 
           return; 
          } 
         } 
        } 


// this function is called when a user presses the "cancel" button on a form. 
private void cancel_encode() 
     { 

      if (p2 != null) 
      { 
       if (p2.HasExited == false) 
        p2.Kill(); 
       if (p2.HasExited == false) 
        p2.WaitForExit(); 
      } 
      if (p != null) 
      { 
       if (p.HasExited == false) 
        p.Kill(); 
       if (p.HasExited == false) 
        p.WaitForExit(); 
      } 
      if (t.IsAlive) 
      { 
       if (!t.Join(2000)) 
        t.Abort(); 
      } 
     } 


// this function sends the error data to my progress window 
void p2_ErrorDataReceived(object sender, DataReceivedEventArgs e) 
     { 
      if (e.Data != null && canceled == false) 
       Invoke(new updateProgressDelegate(this.updateProgress), e.Data); 
     } 

Répondre

1

deux choses

Dans « p2_ErrorDataReceived », vous appelez Invoke(). Cela peut causer une partie de votre impasse. Vous voudrez peut-être changer cela en BeginInvoke(). La documentation de Process.WaitForExit() suggère qu'après avoir appelé Kill(), vous devez appeler la surcharge WaitForExit qui prend un entier, et si elle renvoie true, appelez-la à nouveau sans paramètre pour garantir tous les traitements asynchrones a complété:

p2.Kill(); 
if(p2.WaitForExit(waitTime)) //waitTime is the number of milliseconds to wait 
{p2.WaitForExit();} //waits indefinitely 

//likewise for p 

http://msdn.microsoft.com/en-us/library/ty0d8k56.aspx

+0

En utilisant BeginInvoke() semble avoir fixé! Merci. – Zarxrax