前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家!人工智能学习网站
前言:
大家好,我是上位机马工,硕士毕业4年年入40万,目前在一家自动化公司担任软件经理,从事C#上位机软件开发8年以上!我们在开发上位机软件的过程中,有的时候需要实现同一个进程下的不同线程访问同一个资源的时候不要产生冲突,一个线程访问完了,另一个线程接着访问,或者是不同进程访问同一个资源的时候不要产生冲突,这时候就可以使用Mutex这个互斥锁来实现,Mutex这个类有几个构造函数,常用的分别介绍如下:
1、Mutex()
没有参数的构造函数,可以去实现线程同步。首先new一个Mutex 类的对象,然后在访问同一个资源之前调用WaitOne方法,代表调用WaitOne方法的线程此时独占这个资源,这时候别的线程只能等待这个互斥锁释放了以后才能访问,当我们执行完了我们想要执行的程序以后,再次调用ReleaseMutex方法去释放互斥锁,这时候别的线程就可以接着访问资源了。
public partial class Form1 : Form
{
private static Mutex mut = new Mutex();
public Form1()
{
InitializeComponent();
for (int i = 0; i < 3; i++)
{
Thread myThread = new Thread(new ThreadStart(UseResource));
myThread.Name = String.Format("Thread{0}", i + 1);
myThread.IsBackground = true;
myThread.Start();
}
}
/// <summary>
/// WaitOne到ReleaseMutex之间只能有一个线程进入
/// </summary>
private static void UseResource()
{
// 等待一直到可以安全进入,随后当前线程拥有互斥锁
mut.WaitOne();
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name);
// 模拟工作
Thread.Sleep(500);
Console.WriteLine("{0} is leaving the protected area\r\n",
Thread.CurrentThread.Name);
// 释放互斥锁
mut.ReleaseMutex();
}
}
输出:
Thread1 has entered the protected area
Thread1 is leaving the protected area
Thread3 has entered the protected area
线程 0x85ec 已退出,返回值为 0 (0x0)。
Thread3 is leaving the protected area
Thread2 has entered the protected area
线程 0xec0 已退出,返回值为 0 (0x0)。
Thread2 is leaving the protected area
2、Mutex(Boolean)
这个构造函数传入一个bool类型变量,代表当前线程拥有了互斥锁,这时候就不需要调用WaitOne方法了,因为WaitOne方法也是相当于申请一个互斥锁。
public partial class Form1 : Form
{
private static Mutex mut = new Mutex();
public Form1()
{
InitializeComponent();
// 创建一个互斥锁,当前调用线程拥有互斥锁
mut = new Mutex(true);
for (int i = 0; i < 3; i++)
{
Thread myThread = new Thread(new ThreadStart(UseResource));
myThread.Name = String.Format("Thread{0}", i + 1);
myThread.IsBackground = true;
myThread.Start();
}
Console.WriteLine("当前调用线程拥有互斥体");
Thread.Sleep(1000);
Console.WriteLine("当前调用线程释放互斥体");
mut.ReleaseMutex();
}
/// <summary>
/// WaitOne到ReleaseMutex之间只能有一个线程进入
/// </summary>
private static void UseResource()
{
// 等待一直到可以安全进入,随后当前线程拥有互斥锁
mut.WaitOne();
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name);
// 模拟工作
Thread.Sleep(500);
Console.WriteLine("{0} is leaving the protected area\r\n",
Thread.CurrentThread.Name);
// 释放互斥锁
mut.ReleaseMutex();
}
}
输出:
当前调用线程拥有互斥体
当前调用线程释放互斥体
Thread3 has entered the protected area
Thread3 is leaving the protected area
Thread1 has entered the protected area
线程 0x8cc8 已退出,返回值为 0 (0x0)。
Thread1 is leaving the protected area
Thread2 has entered the protected area
线程 0x57f4 已退出,返回值为 0 (0x0)。
Thread2 is leaving the protected area
3、Mutex(Boolean, String)
这个构造函数拥有两个参数,第一个参数指示调用的当前线程是否拥有互斥锁,第二个参数将这个互斥锁起了一个名字,这样,我们就可以在不同进程之间使用互斥锁,而不仅仅是同一个进程的不同线程下使用了。下面的程序第一次运行以后会弹出一个窗体,提示“关闭弹窗即可释放互斥体”;然后我们再次运行这个程序,两个程序就相当于两个进程了,因为第一个进程的互斥锁没有释放,所以第二次运行程序的时候不会弹出窗体,因为第二次运行的程序会卡在调用WaitOne那里等待第一个程序释放“MyMutex”这个互斥锁,然后当我们关闭第一个程序的弹窗以后,此时由于互斥锁被释放,所以第二个程序的弹窗会弹出来。
public partial class Form1 : Form
{
private static Mutex mut = new Mutex();
public Form1()
{
InitializeComponent();
//与其他进程共享互斥体时,为互斥体起一个名称,比如MyMutex
Mutex m = new Mutex(false, "MyMutex");
Console.WriteLine("等待获取互斥体,如果被一个进程占用,则必须等它释放");
m.WaitOne();
Console.WriteLine("本进程拥有互斥体");
MessageBox.Show("关闭弹窗即可释放互斥体");
m.ReleaseMutex();
}
}
4、Mutex(Boolean, String, Boolean)
这个构造函数有三个参数,第一个参数指示调用的当前线程是否拥有互斥锁,第二个参数将这个互斥锁起了一个名字,第三个参数指示当前互斥锁是否已经被成功创建。下面的程序第一次运行以后弹出一个窗体“关闭弹窗即可释放互斥体”,因为第一次的进程成功拥有了这个互斥锁;第二次运行这个程序因为第一次的进程已经拥有互斥锁,并且没有被释放,所以mutexWasCreated会返回false,这样第二个进程就会卡在调用WaitOne那里。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
bool mutexWasCreated;//互斥锁是否被成功创建
Mutex m = new Mutex(true,"MyMutex",out mutexWasCreated);
if (!mutexWasCreated)//如果互斥锁已经存在,则等待拥有
{
Console.WriteLine("Waiting for the named mutex.");
m.WaitOne();
}
MessageBox.Show("关闭弹窗即可释放互斥体");
m.ReleaseMutex();
}
}
典型应用:
我们用下面的程序可以控制我们的winform程序只能被打开一次,这样就能防止软件被多次打开,在上位机软件开发中经常使用这个技术!
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
bool createNew;
Mutex mt = new Mutex(true, "myMutex", out createNew);
if (createNew)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
MessageBox.Show("程序已经打开!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
Process.GetCurrentProcess().Kill();
}
}
}
作者介绍
马工2017年硕士毕业,一直从事上位机软件开发工作,在我工作的第四年年薪突破了40万+,为了帮助跟我一样从底层出身的上位机软件工程师早日达到高级工程师的水平,早日找到30万+的工作,我根据多年项目经验,总结出了一系列可直接用于项目的C#上位机实战教程推荐给大家,目前在CSDN已经超过一千人订阅,如果你不甘贫庸,想像我一样早日拿到高薪,马工强烈推荐你早日学这套教程,雷军曾说这个世界上有99%的问题别人都遇到过,你要做的不是闷头干!而是找这个领域的专家问一下,这是最快速提升自己的方法!
年入30万+C#上位机实战必备教程推荐(点击下方链接即可访问文章)
1、《C#串口通信从入门到精通》
2、《C#与PLC通信从入门到精通 》
3、《C# Modbus通信从入门到精通》
4、《C#Socket通信从入门到精通 》
5、《C# MES通信从入门到精通》
6、《winform控件从入门到精通》