Frage

schrieb ich einen schnellen und schmutzige Wrapper um svn.exe einige Inhalte abrufen und mit ihm etwas zu tun, aber für bestimmte Eingaben es gelegentlich und reproduzierbar hängt und nicht beenden. Zum Beispiel ist ein Aufruf von svn list:

svn list "http://myserver:84/svn/Documents/Instruments/" --xml  --no-auth-cache --username myuser --password mypassword

Diese Befehlszeile läuft gut, wenn ich es nur von einem Kommando-Shell, aber es hängt in meiner app. Mein c # -Code dies auszuführen ist:

string cmd = "svn.exe";
string arguments = "list \"http://myserver:84/svn/Documents/Instruments/\" --xml  --no-auth-cache --username myuser --password mypassword";
int ms = 5000;
ProcessStartInfo psi = new ProcessStartInfo(cmd);
psi.Arguments = arguments;
psi.RedirectStandardOutput = true;
psi.WindowStyle = ProcessWindowStyle.Normal;
psi.UseShellExecute = false;
Process proc = Process.Start(psi);
StreamReader output = new StreamReader(proc.StandardOutput.BaseStream, Encoding.UTF8);

proc.WaitForExit(ms);
if (proc.HasExited)
{
    return output.ReadToEnd();
}

Dies nimmt die vollen 5000 ms und nie beendet. Verlängerung der Zeit hilft nicht. In einer separaten Eingabeaufforderung, läuft er sofort, so dass ich bin mir ziemlich sicher, dass es zu einer nicht ausreichenden Wartezeit nicht verwendet ist. Für andere Eingänge, jedoch scheint dies zu funktionieren.

Ich habe auch versucht, hier eine separate cmd.exe ausgeführt wird (wo exe ist svn.exe und args ist das Original arg string), aber der Hang noch aufgetreten:

string cmd = "cmd";
string arguments = "/S /C \"" + exe + " " + args + "\"";

Was könnte ich hier vermasseln, und wie kann ich debuggen diese externen Prozess Sachen?

EDIT:

Ich bin gerade erst jetzt um diese zu adressieren. Mucho dank Jon Skeet für seinen Vorschlag, die in der Tat große Werke. Ich habe eine andere Frage über meine Methode des Umgangs mit diesem, aber da ich ein Multi-Threaded-Anfänger bin. Ich möchte Vorschläge auf eklatante Mängel oder irgendetwas sonst stumm zu verbessern. Ich landete eine kleine Klasse zu schaffen, der den stdout-Stream enthält, einen String die Ausgabe zu halten, und eine Flagge zu sagen, wenn es fertig ist. Dann habe ich ThreadPool.QueueUserWorkItem und ging in einer Instanz von meiner Klasse:

ProcessBufferHandler bufferHandler = new ProcessBufferHandler(proc.StandardOutput.BaseStream,
                                                                          Encoding.UTF8);
ThreadPool.QueueUserWorkItem(ProcessStream, bufferHandler);

proc.WaitForExit(ms);
if (proc.HasExited)
{
    bufferHandler.Stop();
    return bufferHandler.ReadToEnd();
}

... und ...

private class ProcessBufferHandler
{
    public Stream stream;
    public StringBuilder sb;
    public Encoding encoding;
    public State state;

    public enum State
    {
        Running,
        Stopped
    }

    public ProcessBufferHandler(Stream stream, Encoding encoding)
    {
        this.stream = stream;
        this.sb = new StringBuilder();
        this.encoding = encoding;
        state = State.Running;
    }
    public void ProcessBuffer()
    {
        sb.Append(new StreamReader(stream, encoding).ReadToEnd());
    }

    public string ReadToEnd()
    {
        return sb.ToString();
    }

    public void Stop()
    {
        state = State.Stopped;
    }
}

Dies scheint zu funktionieren, aber ich bin zweifelhaft, dass dies der beste Weg ist. Ist das sinnvoll? Und was kann ich tun, um es zu verbessern?

War es hilfreich?

Lösung

Eine Standardfrage: Der Prozess wartet könnte für Sie seine Ausgabe zu lesen. Erstellen Sie einen separaten Thread von seiner Standardausgabe zu lesen, während Sie warten auf sie zu verlassen. Es ist ein bisschen wie ein Schmerz, aber das kann auch das Problem sein.

Andere Tipps

Jon Skeet ist direkt auf das Geld!
Wenn Sie nicht Polling kümmern, nachdem Sie Ihr SVN-Befehl starten versuchen Sie dies:

Process command = new Process();
command.EnableRaisingEvents = false;
command.StartInfo.FileName = "svn.exe";
command.StartInfo.Arguments = "your svn arguments here";
command.StartInfo.UseShellExecute = false;
command.StartInfo.RedirectStandardOutput = true;
command.Start();

while (!command.StandardOutput.EndOfStream)
{
    Console.WriteLine(command.StandardOutput.ReadLine());
}

Ich hatte auf einem Client-Maschine eine exe fallen zu lassen und verwenden Process.Start um es zu starten.

Die aufrufende Anwendung hängen würde - die Frage am Ende ihrer Maschine war die exe unter der Annahme zu sein gefährlich und verhindert, dass andere Anwendungen aus dem Starten

.

Rechts die exe klicken und gehen Sie auf Eigenschaften. Hit „Nicht mehr blocken“ in Richtung der Unterseite neben die Sicherheitswarnung.

Ich weiß, das ist eine alte Post, aber vielleicht wird dies jemand helfen. Ich habe dies einige AWS (Amazon Web Services) CLI-Befehle mit .Net TPL Aufgaben auszuführen.

Ich habe so etwas in meiner Befehlsausführung, die innerhalb einer .Net TPL Aufgabe ausgeführt wird, die in meiner WinForm Hintergrund Arbeiter bgwRun_DoWork Methode erstellt wird, die eine Schleife mit while(!bgwRun.CancellationPending) halten. Dies beinhaltet das Lesen der Standardausgabe aus dem Verfahren über einen neuen Thread das .Net Threadpool-Klasse.

private void bgwRun_DoWork(object sender, DoWorkEventArgs e)
{
  while (!bgwRun.CancellationPending)
  {
   //build TPL Tasks
   var tasks = new List<Task>();

   //work to add tasks here

   tasks.Add(new Task(()=>{

     //build .Net ProcessInfo, Process and start Process here

     ThreadPool.QueueUserWorkItem(state =>
       {
           while (!process.StandardOutput.EndOfStream)
           {
               var output = process.StandardOutput.ReadLine();
               if (!string.IsNullOrEmpty(output))
               {
                   bgwRun_ProgressChanged(this, new ProgressChangedEventArgs(0, new ExecutionInfo
                   {
                       Type = "ExecutionInfo",
                       Text = output,
                       Configuration = s3SyncConfiguration
                   }));
               }

               if (cancellationToken.GetValueOrDefault().IsCancellationRequested)
               {
                     break;
               }
           }
       });
   });//work Task

   //loop through and start tasks here and handle completed tasks

  } //end while
}

Ich weiß, dass mein SVN repos langsam manchmal laufen kann, vielleicht 5 Sekunden nicht lang genug ist? Haben Sie die Zeichenfolge kopiert Sie an den Prozess von einem Haltepunkt sind vorbei, so dass Sie positiv sind es Sie nicht für etwas auffordert?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top