WPF应用程序在UI线程上使用WaitForExit启动进程

时间:2013-06-18 23:09:34

标签: c# .net wpf

当我的WPF应用程序执行WINWORD进程并等待它完成时,我遇到了一个奇怪的情况(方法WaitForExit())。

用户关闭Word后,有两种可能性:

  1. 用户在几秒钟后关闭Word,一切顺利。
  2. 用户在一分钟或更长时间后关闭Word,应用程序不再刷新UI(这几乎总是发生)。在Process.WaitForExit()应用程序将行添加到datagrid之后,它立即显示在UI上。如果用户最小化并恢复窗口,它会变黑。但是,如果用户点击按钮但它不再刷新Window UI,它仍会对鼠标点击作出反应。这在多台计算机上可以重现。
  3. 在WinForms中,这肯定是有效的。我真的想知道在WPF中出现这种行为的原因。这可能是Process.WaitForExit()上的长块WPF UI线程的问题吗?

    顺便说一句,我没有设法在后台线程中启动应用程序并等待它在UI线程中完成(我试图显示一个信息窗口,当WINWORD关闭时它会自动关闭)。

    环境:Windows XP和Windows 7,.NET 4.0

1 个答案:

答案 0 :(得分:5)

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

对于.NET 4.5,有一个更好的替代方案

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

StartAndWaitProcess是一样的。)


旧代码,保持一致性:

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

这种变体更糟糕,因为它不必要地阻塞后台线程等待。