《CLR via C#》读书笔记-单实例应用程序

场景

在实际的使用过程中,存在只允许启动一个应用程序的情况。

效果

效果如下:当启动第一个时,可以起来一个实例,再次创建时,弹出提示框
第一次启动
再次启动

解决方案

代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

namespace CreateOnlyOne
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            bool creatNewOne = false;

            using (new Semaphore(0, 1, "theOnlyOne", out creatNewOne))
            {
                if(creatNewOne)
                {
                    Application.Run(new Form1());
                }
                else
                {
                    MessageBox.Show("程序只能启动1个,当前已启动!无法再启动!");
                }
            }

        }
    }
}

分析

1、只能创建一个实例,说明需要在操作系统层有一个“登记表”的功能,已经在登过的,便会有记录。因此,在创建实例时,先判断是否有过登记,若没有,则创建一个实例,否则弹出提示。
2、Semaphore。可以用停车场的例子来说明Semaphore。

以一个停车场是运作为例。为了简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。
在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量(Semaphore)的作用。
更进一步,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。 当一个线程调用Wait(等待)操作时,它要么通过然后将信号量减一,要么一直等下去,直到信号量大于一或超时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是因为加操作实际上是释放了由信号量守护的资源。

其构造器如下:
构造器的说明

在构造器中,最关键的有两个:
1、int initialCount:最开始时,看门人对外宣称可以进来的车辆数。MSDN上的解释:The initial number of requests for the semaphore that can be granted concurrently. 即最开始时,看门人能够一次能够处理的数量。
2、int maximumCount:停车场的最大数。

Semaphore例子

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace SemaphoreExample
{
    class Program
    {
        static Semaphore sem = new Semaphore(2, 2, "PackingSemaphore");

        static void Main(string[] args)
        {

            for (int i = 0; i < 5;i++ )
            {
                Thread td = new Thread(recordPacking);
                td.Name = string.Format("车辆{0}", i);
                td.Start(td.Name);
            }


            Console.ReadKey();
        }


        static void recordPacking(object obj)
        {
            sem.WaitOne();
            Console.WriteLine(obj.ToString()+"进入停车场,时间:"+DateTime.Now.ToString());
            Thread.Sleep(1500);
            Console.WriteLine(obj.ToString() + "离开停车场,时间:" + DateTime.Now.ToString());
            sem.Release();
        }
    }
}

其中有这样一句:

static Semaphore sem = new Semaphore(2, 2, “PackingSemaphore”);

代表,停车场有两个车位,可以同时进来两个车位。所以输出结果为:
可处理状态

当以上这句话,变为:

static Semaphore sem = new Semaphore(0, 2, “PackingSemaphore”);

Semaphore初始化时能处理的请求数为0,则车辆无法进入停车场。(相当于最开始看门人擅自离岗了,因此不管排多少车,一辆都进不去),如图所示:
为0的处理能力

即使是上面情况时,当加入释放的语句后。

    static void Main(string[] args)
        {
            sem.Release(1); //*****就是这句****

            for (int i = 0; i < 5; i++)
            {
                Thread td = new Thread(recordPacking);
                td.Name = string.Format("车辆{0}", i);
                td.Start(td.Name);
            }


            Console.ReadKey();
        }

输出如下:
输出结果

从上面的例子中可以得知Semaphore构造器中第一个参数initialCount的真正含义。
1、范围:限定在初始化。
2、Semaphore一次能够处理的请求数

总结

在知乎上有一个问题:semaphore和mutex的区别?
里面讲的不错,这其中涉及到Mutex与Semaphore的区别。其中“fleuria”的回答很好,无可辩驳。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值