سؤال

I want to ensure that my logic is correct here. I want to run a process for timeout seconds, if it runs for longer it should be immediately killed.

The completed flag should reliably indicate whether the process completed as intended, e.g was not killed, and did not crash or throw an exception.

Also, I am not positive if the check to process.HasExited is correct. If process.WaitForExit() returns false and Kill() succeeds, then will process.HasExited always be true? That would be my assumption but I wanted to confirm. Also, what if anything can be done if Kill() fails, besides just logging?

        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; 
                }
            }
        }
هل كانت مفيدة؟

المحلول

Yes, the HasExited will always be true in your case.

According to MSDN,

"A value of true for HasExited indicates that the associated process has terminated, either normally or abnormally.[...]A process can terminate independently of your code. If you started the process using this component, the system updates the value of HasExited automatically, even if the associated process exits independently."

However, if your process crashes and terminates before your timeout, then your code will set it as completed anyway. Maybe you should check the exit code, but it can have different meanings for each process:

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

For crashes, there are some approaches here and here, but generally you can't detect crashes for all processes.

نصائح أخرى

We use the following in a .net console app

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));
}

In C, you could set an OS alarm using the alarm function. When it expired, a SIGALRM would be sent to your process, which kills it if no handler is set.

You can use this. It is a C# wrapper over the JobObjects functionallity. The idea behind is (low level outline that is embedded inside the library I mentioned):

  1. Create a job object.
  2. Configure the job object to have a time limit of x seconds.
  3. Create a process and before resuming it assing it to the job object.
  4. Resume the process.
  5. The process will be killed by the operating system when the time passes. YOu usually get notified by a non zero return code, or a callback. The JobObject API itself allows callbacks, not sure about the C# wrapper.

Also using job objects you can restrict memory usage. On the page I mentioned you can find examples also.

UPDATE

After I wrote the above statements I have found this Kill child process when parent process is killed. They use the JobObjects for another task, but the usage of JobObjects should be the same as for your case.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top