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的动态代理Proxy

    概念梳理: 1.什么是动态代理? 答:动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实.代理一般会实现它所表示的实际对象的接口.代理可以访问实际对象,但是延迟实现实际对象的部分功能,实际 ...

  2. Redis 设置权限密码,以及如何开启关闭设置

    linux redis 设置密码:   在服务器上,这里以linux服务器为例,为redis配置密码. 1.第一种方式 (当前这种linux配置redis密码的方法是一种临时的,如果redis重启之后 ...

  3. Retrofit总结(原)

    1.Retrofit的作用 A type-safe HTTP client for Android and Java 看到这句话时候在想什么是类型安全? 百度一下:类型安全代码指访问被授权可以访问的内 ...

  4. Sass--嵌套选择器

    Sass 中还提供了选择器嵌套功能,但这也并不意味着你在 Sass 中的嵌套是无节制的,因为你嵌套的层级越深,编译出来的 CSS 代码的选择器层级将越深,这往往是大家不愿意看到的一点.这个特性现在正被 ...

  5. JavaSE---多线程---线程的控制

    1.Java提供了一些工具方法,可以便捷控制线程的执行: 1.1 join Thread提供了让一个线程等待另一个线程执行完成的方法:join: 当某个程序的执行流中调用其他线程的join方法,该线程 ...

  6. Spring 讲解(二 )

    1.Spring 容器加载的3种方式 public class ServiceTest { public static void main(String[] args) { //Spring容器加载有 ...

  7. js消除图片小游戏

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. sed编辑器基础

    一. 更多的替换选项 ①替换标记 root@localhost sed]# cat data4.txt This is a test of the test script. This is the s ...

  9. 获取FileSystem

    /** * 根据配置文件获取HDFS操作对象 * 有两种方法: * 1.使用conf直接从本地获取配置文件创建HDFS对象 * 2.多用于本地没有hadoop系统,但是可以远程访问.使用给定的URI和 ...

  10. CDN技术之--内容缓存工作原理

    有CDN前的网站服务技术–硬件扩展:高成本,灵活性和可扩展性比较差–镜像技术(mirroring):镜像服务器安装有一个可以进行自动远程备份的软件,每隔一定时间,各个镜像服务器就会到网站的源服务器上去 ...