Подтвердить что ты не робот

Application.Current.Shutdown() не убивает мое приложение

Я только начал новый С#/приложение WPF и использую NotifyIcon из WPF Contrib проект. Я могу запустить программу, добавить элемент меню "Выход" в NotifyIcon ContextMenu и связать этот элемент с методом, который просто запускает 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() в другой метод и вызову вместо этого, добавив слой косвенности, кнопка все еще работает, а значок не будет.

Решение найдено?

Только что нашел эту ветку, решение которой здесь работает. Я не совсем понимаю, что происходит, поэтому, если кто-то хочет объяснить, я буду признателен.

4b9b3361

Ответ 1

Вы пробуете Environment.Exit(0); Он убивает процесс с заданным кодом выхода. Код выхода 0 указывает, что приложение успешно завершено. Это может быть более "грубо" или "не сделано", но, возможно, это то, что вы ищете.

Ответ 2

Я обнаружил, что если я создаю потоки, не настроенные на "фон", основное окно /etc будет закрыто, но потоки будут продолжать выполнять.

Другими словами, только потоки фона закрываются, когда заканчивается основной поток. Регулярные потоки, также называемые Thread.IsBackground = false, будут продолжать работать.

Попробуйте использовать thread.IsBackground = true;

P.S. Я предположил, что вы где-то использовали темы.

Ответ 3

У меня была такая же проблема в моем приложении. В моем стартовом модуле (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);
    }
    }

Это происходит непосредственно в процессе, вызывающем зависание. Нет необходимости перебирать несколько процессов.

Ответ 4

Woooow! вам не нужно это делать! просто просто переопределите метод 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);. он выдает одно и то же исключение.

Ответ 5

Он может жить в процессах. Вот пример того, как я проверяю/убиваю процесс

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

Ответ 6

Убедитесь, что вы не создаете никаких объектов Window, которые вы никогда не показываете()

По какой-то безумной причине WPF добавляет окна в Application.Windows в CREATION, а не при первом вызове 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();

Итак, когда viewModel был DogModel, я создал объекты TWO DogWindow, поэтому Application.Windows.Count было 3, когда я ожидал, что оно равно 2. Поскольку Application.Shutdown ожидал закрытия всех окон, он так и не получил активирован - хотя я даже не открыл окно!

Я всегда предполагал, что для активации окна требуется Show(), но это было неправильное предположение - поэтому мое приложение никогда не выходило.

Ответ 7

Я думаю, что ответ автора самый лучший здесь, но на самом деле его не вызывали. Application.Shutdown(), похоже, требуется выполнить в потоке диспетчера для работы. Попробуйте, если вы столкнулись с проблемой:

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