public static void Main(string[] args){ //部分代码略 ManualResetEvent eventx = new ManualResetEvent(false); //① //部分代码略 eventx.WaitOne(Timeout.Infinite, false); //② //部分代码略} 有一个问题想不通, 当我注释掉②的时候,主线程会先执行完下面的代码,线程池里面的线程才执行! 取消注释的时候, 执行到②时,主线程会暂停执行直到线程池的线程都执行完! 我想确认一下,主线程和eventx有什么关联? eventx.WaitOne()是通知主线程暂停执行等待其他线程还是暂停执行eventx? 照这样的话那set()是通知主线程可以执行下去还是通知eventx继续执行?
Set方法将信号置为发送状态,Reset方法将信号置为不发送状态,WaitOne等待信号的发送。可以通过构造函数的参数值来决定其初始状态,若为true则非阻塞状态,为false为阻塞状态。如果某个线程调用WaitOne方法,则当信号处于发送状态时,该线程会得到信号, 继续向下执行。
其区别就在调用后,AutoResetEvent.WaitOne()每次只允许一个线程进入,当某个线程得到信号后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待.也就是说,AutoResetEvent一次只唤醒一个线程;而ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set()方法后,其他调用WaitOne的线程获得信号得以继续执行,而ManualResetEvent不会自动将信号置为不发送。也就是说,除非手工调用了ManualResetEvent.Reset()方法,则ManualResetEvent将一直保持有信号状态,ManualResetEvent也就可以同时唤醒多个线程继续执行。
using System.Threading;namespace ManualResetEventStudy
{ class ThreadClass
{ static ManualResetEvent mre = new ManualResetEvent(false); static void t1()
{
mre.WaitOne(1000);//等待1秒后,自行启动
for (int x = 1; x <= 5; x++)
{
Thread.Sleep(500);
Console.WriteLine("t1的x:" + x);
}
} static void t2()
{
mre.WaitOne();//一直等待下去,直到有"人"调用mre.set()发出信号为止
for (int x = 1; x <= 5; x++)
{
Thread.Sleep(500);
Console.WriteLine("t2的x:" + x);
}
} static void Main(string[] args)
{
Thread thrd1 = new Thread(t1);
thrd1.Start(); Thread thrd2 = new Thread(t2);
thrd2.Start();
for (int x = 1; x <= 5; x++)
{
Thread.Sleep(500);
Console.WriteLine("主线程中的x:" + x); if (x == 3)
{
mre.Set();//通知所有等待的线程:“同志们,可以动啦”:)
}
} Console.Read();
} }
} t1方法中,我们用 mre.WaitOne(1000);让调用该方法的线程先等候1秒,t2方法中,我们用mre.WaitOne()无限等候,然后主线程中计数到3的时候,手动调用mre.Set()方法唤醒所有等候中的线程,运行结果类似下面这样:主线程中的x:1
主线程中的x:2
t1的x:1
主线程中的x:3
t1的x:2
t2的x:1
主线程中的x:4
t1的x:3
主线程中的x:5
t2的x:2
t1的x:4
t2的x:3
t1的x:5
t2的x:4
t2的x:5
这里你可以看到在同一个类中定义的起点函数。using System;
using System.Threading;
namespace ThreadingTester
{
class ThreadClass
{
public static void trmain()
{
for(int x=0;x < 10;x++)
{
Thread.Sleep(1000);
Console.WriteLine(x);
}
}
static void Main(string[] args)
{
Thread thrd1=new Thread(new ThreadStart(trmain));
thrd1.Start();
for(int x=0;x < 10;x++)
{
Thread.Sleep(900);
Console.WriteLine("Main :" + x);
}
}
}
}Thread.Sleep(n)方法把“this”线程置于n毫秒的休眠状态。你可以看看这个例子,在主函数我们定义了一个新的线程,其中它的起点是函数trmain(),我们然后包含了Start()方法开始执行。如果你运行这个例子,你就会了解线程间的切换(让CPU从运行一个线程转到另一个线程)让线程几乎同时运行,为了能看哪个线程运行更快我把主线程设置比新线程少100毫秒。
现在,在开始线程前,先给线程命名:
Thread thrd1=new Thread(new ThreadStart(trmain));
thrd1.Name="thread1";
thrd1.Start();
Thread tr = Thread.CurrentThread;
Console.WriteLine(tr.Name);
在完成上面程序后,设想我们不想在一开始新线程就让它马上运行结束,也就是说,我们开启了一个新线程,让它运行,在某个特定的时间点,新线程暂停并等待从主线程(或其他线程)发来的消息。
我们可以这样定义:
public static ManualResetEvent mre = new ManualResetEvent(false);
ManualResetEvent建立时是把false作为start的初始状态,这个类用于通知另一个线程,让它等待一个或多个线程。注意,为了通知或监听同一个线程,所有的其它线程都能访问那个类。
等待线程这样写:
mre.WaitOne();
这将引起等待线程无限期的阻塞并等待类来通知。
发信号的线程应该这样:
mre.Set();
这样类就会被通知,值变成true,等待线程就会停止等待。在通知事件发生后,我们就可以使用下面语句把线程置于基状态:
mre.Reset();
现在让我们在程序执行一下:using System;
using System.Threading;
namespace ThreadingTester
{
class ThreadClass
{
public static ManualResetEvent mre=new ManualResetEvent(false);
public static void trmain()
{
Thread tr = Thread.CurrentThread;
Console.WriteLine("thread: waiting for an event");
mre.WaitOne();
Console.WriteLine("thread: got an event");
for(int x=0;x < 10;x++)
{
Thread.Sleep(1000);
Console.WriteLine(tr.Name +": " + x);
}
}
static void Main(string[] args){
Thread thrd1=new Thread(new ThreadStart(trmain));
thrd1.Name="thread1";
thrd1.Start();
for(int x=0;x < 10;x++)
{
Thread.Sleep(900);
Console.WriteLine("Main:" + x);
if(5==x) mre.Set();
}
while(thrd1.IsAlive)
{
Thread.Sleep(1000);
Console.WriteLine("Main: waiting for thread to stop");
}
}
}
}
主线程和eventx有什么关联?
eventx.WaitOne()是通知主线程暂停执行等待其他线程 还是 暂停执行eventx直到set()信号发出?