C# 总结ManualResetEvent与AutoResetEvent【一】
ManualResetEvent:
ManualResetEvent 允许线程通过发信号互相通信。通常,此通信涉及一个线程在其他线程进行之前必须完成的任务。当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时,它调用 Reset 以将 ManualResetEvent 置于非终止状态,此线程可被视为控制 ManualResetEvent。调用 ManualResetEvent 上的 WaitOne 的线程将阻止,并等待信号。当控制线程完成活动时,它调用 Set 以发出等待线程可以继续进行的信号。并释放所有等待线程。一旦它被终止,ManualResetEvent 将保持终止状态(即对 WaitOne 的调用的线程将立即返回,并不阻塞),直到它被手动重置。可以通过将布尔值传递给构造函数来控制 ManualResetEvent 的初始状态,如果初始状态处于终止状态,为 true;否则为 false。
案例分析:
1.比如我们现在有两个线程操作以及List<string>集合,一个线程往集合里面加数据,一个线程删数据。现在有这么一个条件,前提是集合里面数据大于5条的时候,才通知删除的线程,来删除集合里面的数据,如果集合里面数据不大于5条,就不执行删除,一直阻塞删除的线程,等待数据大于5条;
定义List<string>集合与ManualResetEvent对象
static List<string> list = new List<string>();
private static ManualResetEvent met = new ManualResetEvent(false);
代码如下:往集合中加数据
/// <summary>
/// 往list里加数据
/// </summary>
/// <returns></returns>
public static List<string> AddtoList()
{
Task.Factory.StartNew(() =>
{
while (true)
{
for (int i = 0; i <= 11; i++)
{
list.Add("list项目" + i);
Console.WriteLine("添加到第" + i);
Thread.Sleep(2000);
}
}
});
return list;
}
从集合中删除数据:
public static void DeteleFromList(List<string> list)
{
Task.Factory.StartNew(() =>
{
while (true)
{
met.WaitOne();//阻塞当前线程
if (list.Count > 0)
{
for (int i = 0; i < list.Count; i++)
{
list.RemoveAt(0);
Console.WriteLine("删除了" + i);
}
}
}
});
}
Main函数中,调用:
static void Main(string[] args)
{
List<string> s = new List<string>();
s = AddtoList();
while (true)
{
if (s.Count >= 5)
{
met.Set();
DeteleFromList(s);
}
if (s.Count == 0)
{
met.Reset();
}
}
}
执行效果:
AutoResetEvent
AutoResetEvent(bool initialState):构造函数,用一个指示是否将初始状态设置为终止的布尔值初始化该类的新实例。
False:无信号,子线程的WaitOne方法不会被自动调用
True:有信号,子线程的WaitOne方法会被自动调用
Reset ():将事件状态设置为非终止状态,导致线程阻止;如果该操作成功,则返回true;否则,返回false。
Set ():将事件状态设置为终止状态,允许一个或多个等待线程继续;如果该操作成功,则返回true;否则,返回false。
WaitOne(): 阻止当前线程,直到收到信号。
WaitOne(TimeSpan, Boolean) :阻止当前线程,直到当前实例收到信号,使用 TimeSpan 度量时间间隔并指定是否在等待之前退出同步域。
WaitAll():等待全部信号。
代码案例 引自:案例来源
static void Main()
{
Request req = new Request();
//线程1干活
Thread GetCarThread = new Thread(new ThreadStart(req.InterfaceA));
GetCarThread.Start();
//线程2干活
Thread GetHouseThead = new Thread(new ThreadStart(req.InterfaceB));
GetHouseThead.Start();
//等待三件事都干成的通知信息
AutoResetEvent.WaitAll(req.autoEvents);
//这个人就开心了。
req.InterfaceC();
System.Console.ReadKey();
}
public class Request
{
//建立事件数组
public AutoResetEvent[] autoEvents = null;
public Request()
{
autoEvents = new AutoResetEvent[]
{
new AutoResetEvent(false),
new AutoResetEvent(false)
};
}
public void InterfaceA()
{
System.Console.WriteLine("请求A接口");
Thread.Sleep(1000*2);
autoEvents[0].Set();
System.Console.WriteLine("A接口完成");
}
public void InterfaceB()
{
System.Console.WriteLine("请求B接口");
Thread.Sleep(1000 * 1);
autoEvents[1].Set();
System.Console.WriteLine("B接口完成");
}
public void InterfaceC()
{
System.Console.WriteLine("两个接口都已经请求完,正在处理C");
}
}
以上是本篇全部内容,请指正;