title author date CreateTime categories
wpf 单例
lindexi
2018-08-10 19:16:53 +0800
2018-2-13 17:23:3 +0800
WPF

本文告诉大家如何做一个 wpf 单例程序。单例就是用户只能运行这个程序一次,也就是内存只有存在这个程序一个。

首先创建项目,右击 App.xaml.cs 选择编译为 Page ,原来是 ApplicationDefinition

打开 App.xaml 删除StartupUri="MainWindow.xaml",不然下面的代码会启动两个窗口

然后创建 Main ,请添加下面代码

    public partial class App : Application
{
App()
{
InitializeComponent();
} [STAThread]
static void Main()
{
App app = new App();
MainWindow window = new MainWindow();
app.Run(window);
}
}

然后就在 Main 写逻辑,这里判断是否有全局锁,如果有就不启动。添加锁的代码很简单。

static Mutex mutex = new Mutex(true, "lindexi");

如果程序没有启动,那么通过下面的代码判断现在只有他一个软件

if (_mutex.WaitOne(TimeSpan.Zero, true))

现在的主函数就是判断可以启动就创建窗口

        static void Main()
{
App app = new App();
if (_mutex.WaitOne(TimeSpan.Zero, true))
{
//如果申请成功
MainWindow window = new MainWindow();
app.Run(window);
}
}

但是如果不能启动,就需要启动原来启动的程序。这里使用一个特殊方法,先创建一个类,可以发送消息给原先的程序。需要知道,在windows上,程序和系统通信都是使用消息,通过模拟消息就可以让其他程序做出特殊的效果,如让他放在窗口最前。

如果需要发送消息,那么需要使用下面的方法。下面代码注册了一个自己的消息,这样在自己的程序可以判断WM_SHOWME来把自己给用户。

    internal class NativeMethods
{
public const int HWND_BROADCAST = 0xffff;
public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");
[DllImport("user32")]
public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
[DllImport("user32")]
public static extern int RegisterWindowMessage(string message);
}

接着修改主函数,在已经启动一个程序,就让他打开。这个方法就是发送一个特殊的消息,只有自己的程序知道这个消息是显示。

        static void Main()
{
App app = new App();
if (_mutex.WaitOne(TimeSpan.Zero, true))
{
//如果申请成功
MainWindow window = new MainWindow();
app.Run(window);
_mutex.ReleaseMutex();
}
else
{
NativeMethods.PostMessage(
(IntPtr) NativeMethods.HWND_BROADCAST,
NativeMethods.WM_SHOWME,
IntPtr.Zero,
IntPtr.Zero);
}
}

然后发送消息需要让程序自己监听,于是打开 MainWindow.xaml.cs 添加下面的代码,如果监听消息是让自己显示,那么就打开自己。

        protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
source.AddHook(WndProc);
} private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
{
if (msg == NativeMethods.WM_SHOWME)
{
Activate();
}
return IntPtr.Zero;
}

这样就可以运行一个程序,再次打开也会打开原来的程序。

但是程序有一个坑,如果是多用户,那么打开只能是一个程序,请看下面的代码。

        private static Mutex _mutex = new Mutex(true, "lindexi" + Environment.UserName);

实际文章就想说如何在多用户系统使用单例。

参见:Writing a custom Main() method for WPF applications — The Stochastic Game

C# .NET Single Instance Application - Sanity Free Coding - C#, .NET, PHP

代码:wpf 单例 PfalmcYmgtx-CSDN下载

2018-8-10-wpf-单例的更多相关文章

  1. Unity 游戏框架搭建 2018 (二) 单例的模板与最佳实践

    Unity 游戏框架搭建 2018 (二) 单例的模板与最佳实践 背景 很多开发者或者有经验的老手都会建议尽量不要用单例模式,这是有原因的. 单例模式是设计模式中最简单的也是大家通常最先接触的一种设计 ...

  2. java基础10 单例模式之饿汉式和懒汉式单例

    前言: 软件行业中有23中设计模式 单例模式    模版模式    装饰者模式    观察者模式    工厂模式    ........... 单例模式 1. 单例模式包括 1.1 饿汉式单例 1.2 ...

  3. Java 基础入门随笔(10) JavaSE版——单例设计模式

    设计模式:对问题行之有效的解决方式.其实它是一种思想. 1.单例设计模式. 解决的问题:就是可以保证一个类在内存中的对象唯一性.(单个实例) 使用单例设计模式需求:必须对于多个程序使用同一个配置信息对 ...

  4. 自己动手写一个简易对象关系映射,ORM(单例版和数据库池版)

    准备知识 DBUtils模块  <<-----重点 DBUtils是Python的一个用于实现数据库连接池的模块 此连接池有两种连接模式: DBUtils提供两种外部接口: Persist ...

  5. Java实现单例的5种方式

    1. 什么是单例模式 单例模式指的是在应用整个生命周期内只能存在一个实例.单例模式是一种被广泛使用的设计模式.他有很多好处,能够避免实例对象的重复创建,减少创建实例的系统开销,节省内存. 2. 单例模 ...

  6. 【iOS 单例设计模式】底层解析与运用

    [iOS 单例设计模式]底层解析与运用 一.单例设计名词解释: (官方解释)单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例.(形象比喻)程序 — 公司   单例实例 - 管理 ...

  7. php : MVC 演示(使用单例工厂)

    此例子是MVC的简单应用, 要达到的效果如下: 用户列表: 姓名 年龄 学历 兴趣 出生地 账号创建时间 操作 keen 20 高中 篮球,足球 广东 2016-11-08 10:00:31 删除 a ...

  8. iOS 页面间几种传值方式(属性,代理,block,单例,通知)

    第二个视图控制器如何获取第一个视图控制器的部分信息 例如 :第二个界面中的lable显示第一个界面textField中的文本 这就需要用到属性传值.block传值 那么第一个视图控制器如何获的第二个视 ...

  9. OC单例快速实现

    首先新建一个头文件,定义如下宏: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ...

  10. JAVA单例

    单例模式: 1 public class Person{ 2 public static Person per//定义一个静态变量,用来储存当前类的对象 3 private Person()//构造方 ...

随机推荐

  1. Java开发中的23种设计模式详解(3)行为型

    本章是关于设计模式的最后一讲,会讲到第三种设计模式--行为型模式,共11种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模 ...

  2. mySQL查看存储过程、函数、视图、触发器

    一.查看存储过程 1.show procedure status; //查看所有的 2.show create procedure proc_AllUser[proc_name]; 查看proc_Al ...

  3. linux的CentOS、Ubuntu、Debian三个比较异同

    Linux有非常多的发行版本,从性质上划分,大体分为由商业公司维护的商业版本与由开源社区维护的免费发行版本.商业版本以Redhat为代表,开源社区版本则以debian为代表.这些版本各有不同的特点,在 ...

  4. Docker两个问题的讨论

    docker中的container到底可不可以理解为一个操作系统? 先表明态度,我的理解是,NO. 主机级虚拟化 容器级虚拟化 容器通过Docker的守护进程(Docker daemon)来进行创建, ...

  5. windows7下搭建robot framework环境

    第一步 安装python并设置环境变量 1.安装python: python下载地址https://www.python.org/,建议用2.7.x版本 2.设置环境变量: 方法如下所示  第二步 安 ...

  6. 属性class与:class

    1.官方的案例 我们可以传给 v-bind:class 一个对象,以动态地切换 class <div v-bind:class="{ active: isActive }"& ...

  7. 数据结构---Java---String、StringBuilder、StringBuffer

    1.概述 1.1 String:不可变字符串 public final class String implements java.io.Serializable, Comparable<Stri ...

  8. MySQL数据类型DECIMAL用法详解

    MySQL DECIMAL数据类型用于在数据库中存储精确的数值.我们经常将DECIMAL数据类型用于保留准确精确度的列,例如会计系统中的货币数据. 要定义数据类型为DECIMAL的列,请使用以下语法: ...

  9. css强制换行和超出部分隐藏实现

    一.强制换行 1 word-break: break-all; 只对英文起作用,以字母作为换行依据. 2 word-wrap: break-word; 只对英文起作用,以单词作为换行依据. 3 whi ...

  10. yii2 后台前后台 前后台登陆、退出问题

    问题描述:我使用前后台分离 配置如下: 'user' => [ 'identityClass' => 'app\models\User', 'enableAutoLogin' => ...