4

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

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

process.HasExited另外,如果检查正确,我也不肯定。如果process.WaitForExit()返回 false 并Kill()成功,那么将process.HasExited 永远为 true?那将是我的假设,但我想确认。另外,如果 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

4 回答 4

4

是的,在您的情况下,HasExited 将始终为真。

根据MSDN

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

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

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

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

于 2013-09-25T13:34:33.210 回答
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));
}
于 2013-09-30T13:21:41.090 回答
1

在 C 语言中,您可以使用警报功能设置操作系统警报。当它过期时,一个 SIGALRM 将被发送到您的进程,如果没有设置处理程序,它将杀死它。

于 2013-09-27T02:55:33.590 回答
1

你可以使用这个。它是JobObjects功能的 C# 包装器。背后的想法是(嵌入在我提到的库中的低级大纲):

  1. 创建作业对象。
  2. 将作业对象配置为具有 x 秒的时间限制。
  3. 创建一个进程并在恢复之前将其分配给作业对象。
  4. 继续该过程。
  5. 当时间过去时,该进程将被操作系统杀死。您通常会收到非零返回码或回调的通知。JobObject API 本身允许回调,不确定 C# 包装器。

还可以使用作业对象来限制内存使用。在我提到的页面上,您也可以找到示例。

更新

在我写完上述语句后,我发现当父进程被杀死时这个 Kill child process。他们将 JobObjects 用于另一个任务,但 JobObjects 的用法应该与您的情况相同。

于 2013-10-01T17:11:21.173 回答