Mutex的WaitOne()函数
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
前几天1-2-3去黑木崖找东方不败玩,听到东方不败抱怨说整天绣花眼睛好累呀,于是1-2-3就给东方不败编了一个活动眼睛的程序。
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
|
class Program>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi {>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi static void Main(string[] args)>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi {>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi // 为截图方便把窗体设小一点>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi Console.WindowWidth = 30; Console.BufferWidth = 30; >çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi Console.WindowHeight = 16; Console.BufferHeight = 16;>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi >çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi Mutex mk = new Mutex(false, "my mutex");>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi for (int i = 0; i < 1000; i++)>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi {>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi mk.WaitOne();>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi for (int j = 0; j < 30; j++)>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi {>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi Console.Write(">");>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi Thread.Sleep(100);>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi }>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi mk.ReleaseMutex();>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi Thread.Sleep(500);>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi }>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi }>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi }>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi >çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
|
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
接连运行此程序的两个实例,把它们并排排放在一起(如下图所示),即可看到箭头从左边的窗体“穿越”到右边窗体的效果了。
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
是 的,我们需要同步两个进程(中的主线程),这个工作需要交给Mutex。Mutex和Monitor的概念十分相似,只不过Monitor是.net内建 的线程同步机制,Mutex是封装了Windows操作系统的线程同步机制;Monitor速度快,Mutex的速度要比Monitor慢很多; Monitor只能用于同步同一进程内的线程;Mutex则可以用于同步隶属于不同进程的线程。
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Mutex的WaitAll()函数
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
现在我们对WC进行了扩建,把mk增加到两个,可是却遇到了两个讲排场的进程,它们都要同时占两个mk才肯办事,所以运行起来的效果和前一个程序一样。
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
class Program
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
{
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
static void Main(string[] args)
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
{
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
// 为截图方便把窗体设小一点
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Console.WindowWidth = 30; Console.BufferWidth = 30;
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Console.WindowHeight = 16; Console.BufferHeight = 16;
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Mutex mk1 = new Mutex(false, "my mutex1");
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Mutex mk2 = new Mutex(false, "my mutex2");
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Mutex[] mks = new Mutex[] { mk1, mk2 };
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
for (int i = 0; i < 1000; i++)
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
{
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Mutex.WaitAll(mks);
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
for (int j = 0; j < 30; j++)
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
{
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Console.Write(">");
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Thread.Sleep(100);
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
}
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
mk1.ReleaseMutex();
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
mk2.ReleaseMutex();
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Thread.Sleep(500);
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
}
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
}
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
}
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Mutex的WaitAny()函数
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
看下这个小程序
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
1 class Program
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
2 {
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
3 static void Main(string[] args)
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
4 {
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
5 // 为截图方便把窗体设小一点
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
6 Console.WindowWidth = 30; Console.BufferWidth = 30;
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
7 Console.WindowHeight = 16; Console.BufferHeight = 16;
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
8
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
9 Mutex mk1 = new Mutex(false, "my mutex1");
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
10 Mutex mk2 = new Mutex(false, "my mutex2");
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
11 Mutex[] mks = new Mutex[] { mk1, mk2 };
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
12
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
13 for (int i = 0; i < 1000; i++)
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
14 {
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
15 int index = Mutex.WaitAny(mks); // 返回值为此进程占用的mk在mks里的index
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
16 Console.Write("Index: " + index.ToString());
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
17 for (int j = 0; j < 30; j++)
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
18 {
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
19 Console.Write(">");
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
20 Thread.Sleep(100);
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
21 }
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
22
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
23 mks[index].ReleaseMutex();
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
24 Thread.Sleep(new Random().Next(100, 3000));
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
25 }
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
26 }
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
27 }
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
如 果同时运行此程序的两个实例,正如本文摘要里所写的,只要mk1和mk2有一个是空闲的,进程就可以进去办事,所以两个进程可以同时输出">"字 符。注意程序的第24行,每个进程在输出30个">"字符后都会随机Sleep 100到3000毫秒,这样就有可能出现mk1和mk2同时空闲的情况,所以就会出现一会儿进程1占用mk1而进程2占用mk2;一会儿进程1占用mk2 而进程2占用mk1的情况(在下图分别用绿色和红色波浪线标出)。
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
EventWaitHandle、AutoResetEvent 和 ManualResetEvent
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
EventWaitHandle的名字与Mutex差了很多,不过它可是Mutex不折不扣的兄弟——它和Mutex都是WaitHandle的子类,用法也差不多。下面这两段程序实现了与本文的第一段程序相同的功能。
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
1) AutoReset
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
class Program
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
{
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
static void Main(string[] args)
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
{
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
// 为截图方便把窗体设小一点
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Console.WindowWidth = 30; Console.BufferWidth = 30;
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Console.WindowHeight = 16; Console.BufferHeight = 16;
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
EventWaitHandle mk = new EventWaitHandle(true, EventResetMode.AutoReset, "my mk");
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
for (int i = 0; i < 1000; i++)
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
{
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
mk.WaitOne();
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
for (int j = 0; j < 30; j++)
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
{
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Console.Write(">");
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Thread.Sleep(100);
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
}
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
mk.Set();
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Thread.Sleep(500);
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
}
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
}
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
}
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
2) ManualReset
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
class Program
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
{
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
static void Main(string[] args)
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
{
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
// 为截图方便把窗体设小一点
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Console.WindowWidth = 30; Console.BufferWidth = 30;
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Console.WindowHeight = 16; Console.BufferHeight = 16;
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
EventWaitHandle mk = new EventWaitHandle(true, EventResetMode.ManualReset, "my mk");
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
for (int i = 0; i < 1000; i++)
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
{
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
mk.WaitOne();
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
mk.Reset(); // 把这行去掉会咋样?
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
for (int j = 0; j < 30; j++)
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
{
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Console.Write(">");
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Thread.Sleep(100);
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
}
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
mk.Set();
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
Thread.Sleep(500);
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
}
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
}
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
}
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
>çÉYûùWfwww.netcsharp.cnS&4~ÅeĪÿi
AutoResetEvent 和 ManualResetEvent 是 EventWaitHandle 的子类,功能都差不多,就不多说了