Мьютекс WPF для одного экземпляра приложения не работает - PullRequest
17 голосов
/ 21 марта 2011

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

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        // check that there is only one instance of the control panel running...
        bool createdNew = true;
        using (Mutex instanceMutex = new Mutex(true, @"Global\ControlPanel", out createdNew))
        {
            if (!createdNew)
            {
                Application.Current.Shutdown();
                return;
            }
        }

        base.OnStartup(e);
    }
}

Ответы [ 7 ]

33 голосов
/ 21 марта 2011

Вы также удаляете мьютекс тем же методом, так что мьютекс живет только в течение этого метода. Храните мьютекс в статическом поле и сохраняйте его в течение всего времени вашего приложения.

28 голосов
/ 21 марта 2011

Вот мой новый код, ответ на который дал @Willem van Rumpt (и @OJ) ...

public partial class App : Application
{
    private Mutex _instanceMutex = null;

    protected override void OnStartup(StartupEventArgs e)
    {
        // check that there is only one instance of the control panel running...
        bool createdNew;
        _instanceMutex = new Mutex(true, @"Global\ControlPanel", out createdNew);
        if (!createdNew)
        {
            _instanceMutex = null;
            Application.Current.Shutdown();
            return;
        }

        base.OnStartup(e);
    }

    protected override void OnExit(ExitEventArgs e)
    {          
        if(_instanceMutex != null)
            _instanceMutex.ReleaseMutex();
        base.OnExit(e);
    }
}
4 голосов
/ 21 марта 2011

Вы уничтожаете Mutex сразу после того, как создали и протестировали его.Вы должны поддерживать ссылку на Mutex на весь срок службы вашего приложения.

Сделайте Mutex членом / полем вашего класса Application.Отключите мьютекс, когда ваше приложение закроется.

3 голосов
/ 24 июля 2014

Как образец расширения:

public static class Extension
{
    private static Mutex mutex;

    public static bool IsOneTimeLaunch(this Application application, string uniqueName = null)
    {
        var applicationName = Path.GetFileName(Assembly.GetEntryAssembly().GetName().Name);
        uniqueName = uniqueName ?? string.Format("{0}_{1}_{2}",
            Environment.MachineName,
            Environment.UserName,
            applicationName);

        application.Exit += (sender, e) => mutex.Dispose();
        bool isOneTimeLaunch;
        mutex = new Mutex(true, uniqueName, out isOneTimeLaunch);
        return isOneTimeLaunch;
    }
}

Класс приложения:

    protected override void OnStartup(StartupEventArgs e)
    {
        if (this.IsOneTimeLaunch())
        {
            base.OnStartup(e);
        }
        else
        {
            this.Shutdown();
        }
    }
1 голос
/ 20 июля 2012

Мне сказали реализовать этот мьютекс-подход в уже разработанном WPF-приложении, которое у нас было. Обход проблемы с использованием переопределения OnStart(), который я обнаружил, был в

App.g.cs

Этот файл находится в

obj\x86\debug\

и содержит функцию main(), так что вы просто помещаете этот фрагмент кода в свою основную функцию.

bool isOnlyInstance = false;
Mutex m = new Mutex(true, @"WpfSingleInstanceApplication", out isOnlyInstance);
if (!isOnlyInstance)
{
    MessageBox.Show("Another Instance of the application is already running.", 
                    "Alert", 
                    MessageBoxButton.OK, 
                    MessageBoxImage.Exclamation);
    return;
}
GC.KeepAlive(m);

но для этого вам нужно оставить BUILD ACTION вашего app.xaml равным ApplicationDefinition

ПРИМЕЧАНИЕ. Возможно, это не лучший способ, так как я новичок. (скажите, пожалуйста, есть ли что-то, что я должен изменить)

1 голос
/ 09 ноября 2011

Я могу предложить более чистый подход, который также вводит полезную концепцию переопределения метода Main в приложении WPF. Кроме того, если вы используете свое решение, посмотрите на диспетчер задач, вы заметите, что новый экземпляр действительно достигает состояния выполнения (вы можете увидеть новый процесс, созданный в списке задач), а затем внезапно закрывается. Подход, предложенный в следующем посте, также позволит избежать этого недостатка. http://blog.clauskonrad.net/2011/04/wpf-how-to-make-your-application-single.html

0 голосов
/ 06 июня 2012

Я сделал это по этой ссылке, просто добавив данный класс и одну строку в вас App.Xaml.cs http://wpfsingleinstance.codeplex.com/

public partial class App : Application    
{
  protected override void OnStartup(StartupEventArgs e) 
  {
        WpfSingleInstance.Make(); //added this is the function of that class 
        base.OnStartup(e);
  }
}
...