Maison >développement back-end >C++ >Pourquoi «Waitforexit» est-il suspendu lorsqu'un processus génère une grande sortie?

Pourquoi «Waitforexit» est-il suspendu lorsqu'un processus génère une grande sortie?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2025-01-29 20:16:10660parcourir

Why Does `WaitForExit` Hang When a Process Generates Large Output?

Dépannage ProcessStartInfo est suspendu avec une sortie abondante

Cet article aborde un problème commun: WaitForExit suspendu indéfiniment lorsqu'un processus génère un grand volume de sortie en utilisant ProcessStartInfo. Cela se produit parce que le tampon interne de ProcessStartInfo pour la redirection de sortie standard et de flux d'erreur a des limitations de taille. Attendre la sortie du processus avant de lire la sortie peut entraîner une impasse; Le processus bloque l'écriture dans un tampon complet, l'empêchant de sortir. De même, l'utilisation de ReadToEnd peut bloquer si le processus ne se ferme pas ou rencontre des erreurs en écrivant à StandardError.

La solution: lecture asynchrone

La clé pour résoudre ceci est la lecture asynchrone. Le code suivant démontre cette approche améliorée, gérant à la fois StandardOutput et StandardError efficacement:

<code class="language-csharp">using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

// ... other using statements ...

Process process = new Process();
process.StartInfo.FileName = "TheProgram.exe";
process.StartInfo.Arguments = "Your arguments";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;

StringBuilder outputBuffer = new StringBuilder();
StringBuilder errorBuffer = new StringBuilder();

AutoResetEvent outputWaitHandle = new AutoResetEvent(false);
AutoResetEvent errorWaitHandle = new AutoResetEvent(false);

process.OutputDataReceived += (sender, e) =>
{
    if (e.Data == null)
    {
        outputWaitHandle.Set(); // Signal completion of output stream
    }
    else
    {
        outputBuffer.AppendLine(e.Data);
    }
};

process.ErrorDataReceived += (sender, e) =>
{
    if (e.Data == null)
    {
        errorWaitHandle.Set(); // Signal completion of error stream
    }
    else
    {
        errorBuffer.AppendLine(e.Data);
    }
};

process.Start();

process.BeginOutputReadLine();
process.BeginErrorReadLine();

// Wait for process exit and data streams with timeout
if (process.WaitForExit(30000) && outputWaitHandle.WaitOne(30000) && errorWaitHandle.WaitOne(30000))
{
    Console.WriteLine("Process completed successfully.");
    Console.WriteLine("Standard Output:\n" + outputBuffer.ToString());
    Console.WriteLine("\nStandard Error:\n" + errorBuffer.ToString());
}
else
{
    Console.WriteLine("Process timed out.");
}

// ... rest of your code ...</code>

Ce code révisé utilise des gestionnaires d'événements asynchrones (OutputDataReceived et ErrorDataReceived) pour traiter simultanément des flux de sortie et d'erreur, empêchant le blocage. Les signaux AutoResetEvent sont utilisés pour indiquer la fin de chaque flux. Un délai d'expiration est inclus dans WaitForExit et WaitOne pour éviter les pendus indéfinis. Cela garantit une manipulation robuste des grands flux de sortie.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn