ManualResetEvent可以通知一个或多个正在等待的线程已发生事件,允许线程通过发信号互相通信,来控制线程是否可以访问资源。 当一个线程开始一个活动(此活动必须完成后,其他线程才能开始执行)时,它调用Reset将ManualResetEvent置于非终止状态。此线程可被视为控制ManualResetEvent。 调用ManualResetEvent上的WaitOne的线程将被阻止,并等待信号。当主控线程完成活动时,它调用Set以发出等待线程可以继续进行的信号,并释放所有等待线程。 一旦它被终止,ManualResetEvent将保持终止状态,直到它被手动重置,即对WaitOne的调用将立即返回。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ManualResetEventDemo
{
class Program
{
static void Main(string[] args)
{
MyThread myth = new MyThread();
while (true)
{
Console.WriteLine("输入 stop 后台线程挂起 start 后台线程开始执行!");
string cmd = Console.ReadLine();
if (cmd.ToLower().Trim() == "stop")
{
Console.WriteLine("后台线程停止运行...");
myth.Stop();
}
else if (cmd.ToLower().Trim() == "start")
{
Console.WriteLine("后台线程开始执行...");
myth.Start();
}
}
}
}
/// <summary>
/// | 调用Set被控线程可执行 |
/// |------------------------>|
/// | |
/// 主控线程 |---->ManualResetEvent--->|被控线程
/// | 控制信号 |
/// | |
/// |------------------------>|
/// |调用Reset被控线程停止运行 |
/// </summary>
class MyThread
{
Thread t = null;
// ManualResetEvent允许线程通过发信号互相通信。通常,此通信涉及一个线程在其他线程进行之前必须完成的任务。
// 通过将布尔值传递给构造函数来控制ManualResetEvent的初始状态,如果初始状态处于终止状态,为true,否则为false。
ManualResetEvent manualEvent = new ManualResetEvent(false); // 为true,一开始就可以执行,为false,后台线程处于阻塞态。
private void Run()
{
while (true)
{
// 调用ManualResetEvent上的WaitOne方法的线程,称为被控线程。
// 当主控线程调用ManualResetEvent上的Set方法,发出等待线程可以继续进行的信号,并释放所有等待线程,被控线程可执行。此时ManualResetEvent处于终止状态
// 当主控线程调用ManualResetEvent上的Reset方法,被控线程将阻塞,并等待信号。此时ManualResetEvent处于非终止状态。
manualEvent.WaitOne();
Console.WriteLine("线程id:{0}",Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(200);
}
}
public void Start()
{
manualEvent.Set();
}
public void Stop()
{
manualEvent.Reset();
}
public MyThread()
{
t = new Thread(Run);
t.IsBackground = true;
t.Start();
}
}
}