いくつかのコンテンツを取得して何かを実行するために、svn.exe の周りに簡単で汚いラッパーを書きましたが、特定の入力に対して、時折、再現可能にハングし、終了しません。たとえば、1 つの呼び出しは svn list に対するものです。
svn list "http://myserver:84/svn/Documents/Instruments/" --xml --no-auth-cache --username myuser --password mypassword
このコマンド ラインは、コマンド シェルから実行すると正常に動作しますが、アプリでハングします。これを実行する私の c# コードは次のとおりです。
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();
}
これには 5000 ミリ秒かかり、決して終了しません。時間を延ばしてもダメ。別のコマンド プロンプトでは、すぐに実行されるので、待ち時間の不足とは無関係であると確信しています。ただし、他の入力については、これでうまくいくようです。
また、ここで別の cmd.exe を実行しようとしました (exe は svn.exe で、args は元の引数文字列です) が、それでもハングが発生しました。
string cmd = "cmd";
string arguments = "/S /C \"" + exe + " " + args + "\"";
ここで何を台無しにすることができますか?また、この外部プロセスのものをどのようにデバッグできますか?
編集:
私は今、これに対処しようとしています。ムーチョは、Jon Skeet の提案に感謝します。ただし、私はマルチスレッドの初心者なので、これを処理する方法について別の質問があります。明らかな欠陥やその他のばかげたことを改善するための提案が欲しい. 最終的に、stdout ストリーム、出力を保持する StringBuilder、および終了を通知するフラグを含む小さなクラスを作成しました。次に、ThreadPool.QueueUserWorkItem を使用して、クラスのインスタンスを渡しました。
ProcessBufferHandler bufferHandler = new ProcessBufferHandler(proc.StandardOutput.BaseStream,
Encoding.UTF8);
ThreadPool.QueueUserWorkItem(ProcessStream, bufferHandler);
proc.WaitForExit(ms);
if (proc.HasExited)
{
bufferHandler.Stop();
return bufferHandler.ReadToEnd();
}
... と ...
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;
}
}
これは機能しているように見えますが、これが最善の方法であるかどうかは疑わしいです。これは合理的ですか?そして、それを改善するにはどうすればよいですか?