Application.Current.Shutdown()没有杀死我的应用程序

时间:2011-02-21 20:51:12

标签: c# wpf visual-studio

我刚刚开始使用新的C#/ WPF应用程序并使用WPF Contrib project中的NotifyIcon。我可以启动程序,在NotifyIcon的ContextMenu中添加一个“Exit”MenuItem,并将该项链接到一个只运行Application.Current.Shutdown()的方法。

这会关闭主窗口和NotifyIcon,但会继续运行 - 从VS运行,它不会离开调试模式。什么还在运行?或者我该如何检查?

修改

我刚刚尝试添加一个调用Application.Current.Shutdown()的按钮,并且该按钮正常退出。只有从NotifyIcon调用时才会出现问题。为什么会这样?

为了澄清,我有以下XAML:

<Window x:Class="VirtualBoxManager.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:av="http://schemas.codeplex.com/wpfcontrib/xaml/presentation"
    Title="VirtualBox Manager" Height="350" Width="525"
    ShowInTaskbar="False" WindowStyle="None">
<Grid>
    <av:NotifyIcon Icon="/icon/path"
                   Text="Virtual Machine Manager"
                   Name="notifyIcon">
        <FrameworkElement.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Exit" Click="MenuItemExit_Click" />
            </ContextMenu>
        </FrameworkElement.ContextMenu>
    </av:NotifyIcon>
    <Button Content="Button" Click="button1_Click" />
</Grid>

button1_Click和MenuItemExit_Click都是相同的,但前者成功退出应用,而后者则没有。

进一步的实验:即使我将Application.Current.Shutdown()移动到另一个方法并调用它,添加一个间接层,仍然按钮工作,图标不工作。

找到解决方案?

刚刚找到this thread,谁的解决方案在这里工作。我不完全理解发生了什么,所以如果有人关心解释我会很感激。

7 个答案:

答案 0 :(得分:18)

你可以尝试Environment.Exit(0);它使用给定的退出代码终止进程。退出代码0表示应用程序已成功终止。它可能更“粗鲁”或“未完成”,但也许这就是你要找的东西。

答案 1 :(得分:8)

我发现如果创建未设置为“background”的线程,主窗口/ etc将关闭,但线程将继续运行。

换句话说,只有后台线程在主线程结束时自行关闭。常规线程,即Thread.IsBackground = false,将使进程保持运行。

尝试使用thread.IsBackground = true;

P.S。我假设你在某处使用了线程。

答案 2 :(得分:4)

我的申请中遇到了同样的问题。在我的启动模块(Startup.cs)中,我发现这对我有用:

Process.GetCurrentProcess().Kill();

代码如下:

class StartUp
{
    [STAThread]
    public static void Main()
    {

    try
    {
        Process[] processes = new Process[6];
        App app = new App();
        app.InitializeComponent();
        app.Run();
        Process.GetCurrentProcess().Kill(); //Must add this line after app.Run!!!
    }
    catch (Exception e)
    {
        MessageBox.Show(e.Message);
    }
    }

这直接导致导致挂起的过程。无需迭代多个流程。

答案 3 :(得分:3)

你不需要这样做!只需简单地覆盖主窗口中的OnClosing方法,如下所示:

        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            try
            {
                // there is a bug (throw CrossThreadException) in notifyIcon when disposing from ViewModel.
                notifyIcon.Dispatcher.Invoke(new Action(delegate
                {
                    notifyIcon.Dispose();
                }));
            }
            catch { }
            base.OnClosing(e);
        }

然后在主应用程序代码的任何地方,无论您是在View或ViewModel中还是在任何地方,只需将其称为:

Application.Current.MainWindow.Close();

我有同样的问题,但我这样解决了。

更新:您不应使用Environment.Exit(0);方法。它引发了同样的异常。

答案 4 :(得分:0)

它可能生活在这些过程中。这是我如何检查/终止进程的示例

       const string str = "MRS_Admin";
        foreach (Process process in Process.GetProcesses())
        {
            if (process.ProcessName.StartsWith(str))
            {
                Console.WriteLine(@"Killing process " + str);
                process.Kill();
            }
        }

答案 5 :(得分:0)

确保您没有创建任何您从未显示的Window对象()

出于某种疯狂的原因,WPF会在CREATION上向Application.Windows添加窗口,而不是在您第一次调用Show()时。如果您将Application.Current.Shutdown设置为ShutdownMode.OnLastWindowClose,则这些窗口(您甚至从未显示过)将阻止该应用关闭。

假设您打开主窗口的子窗口,就像这样

Console.WriteLine("Window count : " + Application.Windows.Count);
var window = new OrderDetailsWindow();
Console.WriteLine("Window count : " + Application.Windows.Count);
window.Show();

在您调用Show()之前,您会看到Applications.Windows现在显示2.该应用只会在Windows.Count为零时关闭。


我的情况:

我有一个WindowFactory,它接受一个viewmodel并为传入的模型创建一个窗口。

多年来,我的副本和粘贴已经产生了这个:

 if (viewModel is DogModel)
 {
     window = new DogWindow();
 }
 else if (viewModel is CatViewModel) 
 {
      window = new CatWindow();
 }
 if (viewModel is DogModel)          
 {
     window = new DogWindow();    
 }

 window.DataContext = viewModel;
 window.Show();

所以当viewModelDogModel时,我最终创建了两个DogWindow个对象,因此Application.Windows.Count为3,当我预期它为2.自Application.Shutdown以来等待所有窗户关闭它从未被激活 - 即使我甚至没有打开窗户!

我一直认为激活窗口需要Show(),但这是一个错误的假设 - 所以我的应用程序永远不会退出。

答案 6 :(得分:0)

我认为作者的答案是最好的答案,但还没有被提及。 Application.Shutdown()似乎需要在调度程序线程上执行才能工作。如果遇到问题,请尝试此操作:

Application.Current.Dispatcher.Invoke(Application.Current.Shutdown);