Voki
Voki

Reputation: 3

WPF application starting process with WaitForExit on UI thread

I have a strange situation when my WPF application executes WINWORD process and wait for it to finish (method WaitForExit()).

Once user closes Word, there are two possibilities:

  1. user closes Word after few seconds and everything goes well.
  2. user closes Word after minute or more and application does not refresh UI anymore (this happens almost always). Immediately after Process.WaitForExit() application adds row to datagrid but it is not shown on UI. If user minimizes and restores window, it goes black. But it still reacts to mouse clicks if user hits button but it does not refresh Window UI anymore. This is reproducible on multiple computers.

In WinForms this was working for sure. I would really like to know the reason for such behavior in WPF. Could this be a problem to long block of WPF UI thread on Process.WaitForExit()?

btw, I didn't manage to start application in background thread and wait for it to finish in UI thread (I tried to show an information window that would be automatically closed when WINWORD closes).

Environment: Windows XP and Windows 7, .NET 4.0

Upvotes: 0

Views: 2722

Answers (1)

Vlad
Vlad

Reputation: 35594

Variant for .NET 4.0:

void Button_Click(object sender, RoutedEventArgs e)
{
    var t = StartAndWaitProcess(@"some\document\path");
    t.ContinueWith(dummy => b.Content = "process finished",
                   TaskScheduler.FromCurrentSynchronizationContext());
}

Task StartAndWaitProcess(string path)
{
    var p = new Process();
    p.StartInfo.FileName = path;
    p.EnableRaisingEvents = true;
    var tcs = new TaskCompletionSource<bool>();
    p.Exited += (sender, args) => { tcs.SetResult(true); p.Dispose(); };
    Task.Factory.StartNew(() => p.Start());
    return tcs.Task;
}

For .NET 4.5 there is a nicer alternative

async void Button_Click(object sender, RoutedEventArgs e)
{
    await StartAndWaitProcess(@"some\document\path");
    b.Content = "process finished";
}

(StartAndWaitProcess is the same.)


Old code, kept for consistency:

async void Button_Click(object sender, RoutedEventArgs e)
{
    var t = Task.Run(() => StartAndWaitProcess(@"some\document\path"));
    await t;
    label.Content = "process finished";
}

void StartAndWaitProcess(string path)
{
    using(var p = Process.Start(path))
        p.WaitForExit();
}

This variant is worse, as it unnecessarily blocks a background thread for waiting.

Upvotes: 6

Related Questions