在一个时间限制内杀死进程的逻辑

时间:2013-09-19 00:35:23

标签: c# .net process waithandle

我想确保我的逻辑在这里是正确的。我想在timeout秒运行一个进程,如果它运行的时间更长,它应立即被杀死。

completed标志应该可靠地指示进程是否按预期完成,例如未被杀死,并且没有崩溃或抛出异常。

另外,如果对process.HasExited的检查是正确的,我不肯定。如果process.WaitForExit()返回false并且Kill()成功,那么process.HasExited 总是是真的吗?这将是我的假设,但我想证实。另外,如果Kill()失败,可以做什么呢? 除了记录?

        using (process = new Process())
        {
            process.EnableRaisingEvents = true;
            process.OutputDataReceived += new DataReceivedEventHandler(OnOutputDataReceived);
            process.ErrorDataReceived += new DataReceivedEventHandler(OnErrorDataReceived); 
            process.Exited += new EventHandler(OnExited);

            process.StartInfo = startInfo;
            process.Start();

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

            if (!process.WaitForExit(timeout))
            {
                try
                {
                    process.Kill(); 
                }
                catch (Exception e)
                {
                    LogError(e, MethodBase.GetCurrentMethod());
                }
                finally
                {
                    this.completed = false;
                }
            }
            else
            {
                if (process.HasExited)
                {
                    this.code = process.ExitCode; 
                    this.completed = true;
                }
                else
                {
                    this.completed = false; 
                }
            }
        }

4 个答案:

答案 0 :(得分:4)

是的,HasExited在您的情况下将始终如此。

根据MSDN

HasExited的值为true表示关联的进程已终止,正常或异常 [...] 进程可以独立终止如果您使用此组件启动了该过程,系统会自动更新HasExited的值,即使关联的进程独立退出

但是,如果您的进程在超时之前崩溃并终止,那么您的代码无论如何都会将其设置为已完成。也许您应该检查退出代码,但每个进程可以有different meanings

if (process.ExitCode != 0)
{
    this.completed = false;
}

对于崩溃,有一些方法herehere,但通常您无法检测到所有进程的崩溃。

答案 1 :(得分:2)

我们在.net控制台应用

中使用以下内容
private void InitTimer()
{
    double lInterval = Convert.ToDouble(AppSettings("MaxExecutionTime"));
    lInterval = lInterval * 60 * 1000;
    tm = new System.Timers.Timer(lInterval); // global timer object
    tm.Elapsed += OnTimedEvent;
    tm.Enabled = true;
}

public void ThreadProc(object stateinfo)
{
    // set error code here
    Environment.Exit(0);
}

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
   Threading.ThreadPool.QueueUserWorkItem(new Threading.WaitCallback(ThreadProc));
}

答案 2 :(得分:1)

在C中,您可以使用闹钟功能设置OS闹钟。当它过期时,SIGALRM将被发送到您的进程,如果没有设置处理程序,它将终止它。

答案 3 :(得分:1)

您可以使用this。它是JobObjects函数的C#包装器。 背后的想法是(我提到的库中嵌入了低级轮廓):

  1. 创建一个工作对象。
  2. 将作业对象配置为具有x秒的时间限制。
  3. 创建一个进程,然后再恢复它,将其分配给作业对象。
  4. 恢复过程。
  5. 当时间过去后,操作系统将终止该进程。你通常会收到非零返回码或回调通知。 JobObject API本身允许回调,不确定C#包装器。
  6. 同样使用作业对象可以限制内存使用量。 在我提到的page上,你也可以找到例子。

    <强>更新

    在我写完上述陈述后,我发现了Kill child process when parent process is killed。他们将JobObjects用于另一项任务,但JobObjects的用法应与您的案例相同。