J'ai des problèmes pour rediriger la sortie de la console vers une zone de texte Windows Forms. Le problème est lié au thread. Je dirigeais une application console de la manière suivante,Comment puis-je rediriger la sortie d'un programme de console vers une zone de texte de manière sûre pour les threads?
private void RunConsoleApp()
{
Process proc = new Process();
proc.StartInfo.FileName = "app.exe";
proc.StartInfo.Arguments = "-a -b -c";
proc.StartInfo.UseShellExecute = false;
// set up output redirection
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.EnableRaisingEvents = true;
proc.StartInfo.CreateNoWindow = true;
// Set the data received handlers
proc.ErrorDataReceived += proc_DataReceived;
proc.OutputDataReceived += proc_DataReceived;
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit();
if (proc.ExitCode == 0)
{
out_txtbx.AppendText("Success." + Environment.NewLine);
}
else
{
out_txtbx.AppendText("Failed." + Environment.NewLine);
}
}
puis capturer et traiter les données avec ce gestionnaire de sortie,
// Handle the date received by the console process
void proc_DataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
{
if ((e.Data.EndsWith("DONE.")) || (e.Data.EndsWith("FAILED.")) ||
(e.Data.StartsWith("RESET")))
{
// This crashes the application, but is supposedly the correct method
this.AppendText(e.Data + Environment.NewLine);
// This works, but the debugger keeps warning me that the call
// is not thread safe
//out_txtbx.AppendText(e.Data + Environment.NewLine);
}
}
}
Le texte de la console est alors ajouté comme celui-ci,
delegate void AppendTextDelegate(string text);
// Thread-safe method of appending text to the console box
private void AppendText(string text)
{
// Use a delegate if called from a different thread,
// else just append the text directly
if (this.out_txtbx.InvokeRequired)
{
// Application crashes when this line is executed
out_txtbx.Invoke(new AppendTextDelegate(this.AppendText), new object[] { text });
}
else
{
this.out_txtbx.AppendText(text);
}
}
De toute la documentation et des exemples que j'ai vu cela semble être la méthode correcte, sauf que cela plante l'application quand out_txtbx.Invoke est appelée.
Qu'est-ce qui pourrait être brisé et quelles autres façons de faire?
Solution (comme l'a souligné Hans Passant)
Le problème est que l'application est coincé dans une "étreinte mortelle" en raison de la ligne,
proc.WaitForExit();
Cette ligne doit être supprimée et la méthode doit ressembler à ceci,
private void RunConsoleApp()
{
Process proc = new Process();
proc.StartInfo.FileName = "app.exe";
proc.StartInfo.Arguments = "-a -b -c";
proc.StartInfo.UseShellExecute = false;
// set up output redirection
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.EnableRaisingEvents = true;
proc.StartInfo.CreateNoWindow = true;
// Set the data received handlers
proc.ErrorDataReceived += proc_DataReceived;
proc.OutputDataReceived += proc_DataReceived;
// Configure the process exited event
proc.Exited += new EventHandler(ProcExited);
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
// This blocks the main thread and results in "deadly embrace"
// The Process.Exited event should be used to avoid this.
//proc.WaitForExit();
}
et un gestionnaire d'événements doit être fourni,
/// <summary>
/// Actions to take when console process completes
/// </summary>
private void ProcExited(object sender, System.EventArgs e)
{
Process proc = (Process)sender;
// Wait a short while to allow all console output to be processed and appended
// before appending the success/fail message.
Thread.Sleep(40);
if (proc.ExitCode == 0)
{
this.AppendText("Success." + Environment.NewLine);
ExitBootloader();
}
else
{
this.AppendText("Failed." + Environment.NewLine);
}
proc.Close();
}
Quelle erreur obtenez-vous? – SLaks
Et sur quelle ligne ?? – decyclone
Je l'ai fait sans erreur. S'il n'y a pas de réponse adéquate au moment où je pourrai accéder à mon exemple de code, je posterai. Notez que ce sera plus tard ce soir quand je rentre à la maison. J'avais créé un objet TextWriter qui écrivait dans une zone de texte, puis dirigeais Console.SetOut vers TextWriter. Voir http://msdn.microsoft.com/en-us/library/system.console.setout%28v=VS.90%29.aspx – IAbstract