简体   繁体   中英

Process.Start is causing my WPF program to crash

I have a WPF program that opens a Word document in an process and waits for the process to finish before continuing. If I leave Word open for a few hours my program crashes.

I can see memory for my app steadily increasing while the process is running.

I tried 2 ways to do this and both have the same memory issue.

Way #1

public void ShowExternalReference(string externalRef, bool waitForCompletion)
{
    if (!string.IsNullOrEmpty(externalRef))
    {
        using (var p = Process.Start(@externalRef))
        {
            if (waitForCompletion)
            {
                // Wait for the window to finish loading.
                p.WaitForInputIdle();

                // Wait for the process to end.
                p.WaitForExit();
            }
        }
    }
}

Way #2

public void ShowExternalReference(string externalRef, bool waitForCompletion)
{
    if (!string.IsNullOrEmpty(externalRef))
    {
        using (var p = Process.Start(@externalRef))
        {
            if (waitForCompletion)
            {
                while (!p.HasExited)
                {
                    Thread.Sleep(1000);
                }
            }
        }
    }
}

Any ideas?

I've read comments and it seems to be a memory problem with WaitForExit() for a long time.

So I would do something like that:

  1. Launch process and retrieve only its PID
  2. Regularly check if process is still active

Perhaps this will not produce the same memory issue.

My proposal:

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{

    private System.Threading.Timer _timer;

    public MainWindow()
    {
        InitializeComponent();

        this.Content = new TextBlock() { Text = "Close notepad.exe when you want..." };

        // - Launch process
        Process p = Process.Start("notepad.exe");
        int processId = p.Id;
        _timer = new System.Threading.Timer(new System.Threading.TimerCallback(o => CheckPID((int)o)), processId, 0, 1000);
    }

    /// <summary>
    /// Check if Process has exited
    /// </summary>
    /// <remarks>This code is NOT in UI Thread</remarks>
    /// <param name="processId">Process unique ID</param>
    private void CheckPID(int processId)
    {
        bool stillExists = false;
        //Process p = Process.GetProcessById(processId); // - Raises an ArgumentException if process has alredy exited
        Process p = Process.GetProcesses().FirstOrDefault(ps => ps.Id == processId);
        if (p != null)
        {
            if (!p.HasExited)
                stillExists = true;
        }

        // - If process has exited, do remaining work and stop timer
        if (!stillExists)
        {
            _timer.Dispose();

            // - Ask UI thread to execute the final method
            Dispatcher.BeginInvoke(new Action(ExternalProcessEnd), null);
        }
    }


    /// <summary>
    /// The external process is terminated
    /// </summary>
    /// <remarks>Executed in UI Thread</remarks>
    private void ExternalProcessEnd()
    {
        MessageBox.Show("Process has ended");
    }

}

The drawback is that we won't be able to retrieve StandardOutput, StandardError and ExitStatus.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM