单个应用程序实例的WPF互斥锁无法正常工作

时间:2011-03-21 10:12:35

标签: c# wpf mutex

我正在尝试使用互斥方法只允许我的应用程序的一个实例运行。也就是说 - 我只想为一台机器上的所有用户提供最多一个实例。我已经阅读了关于这个问题的各种其他线程,解决方案看起来很简单,但在测试中我不能让我的第二个实例不能运行。这是我的代码......

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 个答案:

答案 0 :(得分:33)

您也使用相同的方法处理互斥锁,因此互斥锁仅在方法持续时间内存在。将互斥锁存储在静态字段中,并在应用期间保持活动状态。

答案 1 :(得分:28)

这是我的新代码,答案由@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);
    }
}

答案 2 :(得分:4)

您在创建互联网并进行测试后立即销毁互斥锁​​。您需要在应用程序的生命周期内保持Mutex引用处于活动状态。

使Mutex成为Application类的成员/字段。 当应用程序关闭时释放互斥锁。

答案 3 :(得分:3)

作为扩展样本:

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

App类:

    protected override void OnStartup(StartupEventArgs e)
    {
        if (this.IsOneTimeLaunch())
        {
            base.OnStartup(e);
        }
        else
        {
            this.Shutdown();
        }
    }

答案 4 :(得分:1)

我可以建议一种更清晰的方法,它也会引入覆盖WPF应用程序中Main方法的有用概念。此外,如果使用您的解决方案,您可以查看任务管理器,您会注意到新实例实际上已达到执行状态(您可以看到在任务列表中创建的新进程),然后突然关闭。在随后的帖子中提出的方法也将避免这种缺点。 http://blog.clauskonrad.net/2011/04/wpf-how-to-make-your-application-single.html

答案 5 :(得分:1)

我被告知要在我们已经开发的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);

但为此,您需要将app.xaml的BUILD ACTION设置为ApplicationDefinition

注意:这可能不是最佳方式,因为我是初学者。 (请告诉我是否有什么要改变的地方)

答案 6 :(得分:0)

我是通过此链接完成此操作,只需在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);
  }
}