私は一日中トラブルシューティングを行ってきました。いくつかの調査と多くの試行錯誤を行った後、への呼び出しがprocess.Start()
タイマースレッドで機能しないという事実に問題を絞り込むことができたようです。以下のコードは、メイン スレッドで実行されている場合に機能します。まったく同じコードをタイマー コールバックに入れると、ハングします。なんで?タイマーで動作させるにはどうすればよいですか?
private static void RunProcess()
{
var process = new Process();
process.StartInfo.FileName = "cmd";
process.StartInfo.Arguments = "/c exit";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start(); // code hangs here, when running on background thread
process.StandardOutput.ReadToEnd();
process.WaitForExit();
}
編集
テストとして、これとまったく同じコードを別のラップトップで使用したところ、同じ問題が発生しました。これは、コンソール アプリに貼り付けることができる完全なコードです。process.Start()
ハングしますが、終了するキーを押すとすぐprocess.Start()
に、プログラムが終了する前に完了します。
private static System.Timers.Timer _timer;
private static readonly object _locker = new object();
static void Main(string[] args)
{
ProcessTest();
Console.WriteLine("Press any key to end.");
Console.ReadKey();
}
private static void ProcessTest()
{
Initialize();
}
private static void Initialize()
{
int timerInterval = 2000;
_timer = new System.Timers.Timer(timerInterval);
_timer.Elapsed += new ElapsedEventHandler(OnTimerElapsed);
_timer.Start();
}
private static void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
if (!Monitor.TryEnter(_locker)) { return; } // Don't let multiple threads in here at the same time.
try
{
RunProcess();
}
finally
{
Monitor.Exit(_locker);
}
}
private static void RunProcess()
{
var process = new Process();
process.StartInfo.FileName = "cmd";
process.StartInfo.Arguments = "/c exit";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start(); // ** HANGS HERE **
process.StandardOutput.ReadToEnd();
process.WaitForExit();
}