![](/img/trans.png)
[英]What resources do AutoResetEvent / ManualResetEvent consume?
[英]What does AutoResetEvent.Set() do ?
如果我这样做:
private static System.Threading.AutoResetEvent event_2 = new System.Threading.AutoResetEvent(false);
然后在主线程中我做:
event_2.Set();
它将状态从false
更改为true
?
如果是这样,它基本上做到了:
AutoResetEventState = !AutoResetEventState
?
它将状态设置为允许线程在Wait()
上继续执行的状态。
如果有任何线程已经在等待,那么将允许一个线程进行并且状态将立即设置为未设置,因此所有其他线程将继续阻塞。
如果当前没有线程正在等待,那么将立即允许第一个等待,但后续线程将阻塞。
其他EventWaitHandle
派生的类共享相同的通用机制,但允许进行的线程的自动重置与ManualResetEvent
不同,因此名称也不同。
如果将true
传递给构造函数,则初始状态发出信号(允许线程进行),如果传递false
则不发出信号,因此传递true
与构造后立即调用Set()
相同,而传递false
则相反就像你调用Reset()
。
线程通过在AutoResetEvent上调用WaitOne来等待信号。 如果AutoResetEvent处于非信号状态,则线程阻塞,等待当前控制资源的线程通过调用Set来指示资源可用。
调用Set信号AutoResetEvent释放等待线程。 AutoResetEvent保持信号状态,直到释放单个等待线程,然后自动返回到非信号状态。 如果没有线程在等待,则状态将无限期地发出信号。
要添加到其他答案,您需要这个的原因(而不是具有bool
属性,您只需切换)是:
信令:将在e.WaitOne()
处阻止的线程将发出信号 ,其中一个将继续。 如果你想在没有同步原语的情况下自己这样做,你必须实现某种轮询; “阻塞”线程必须定期轮询bool
(或者说, int
)字段以检查它是否已更改并允许继续。 如果不出意外,这会不必要地消耗cpu周期并且会有延迟(取决于你的轮询间隔)。
原子性:如果多个线程在等待,您可以保证只有一个线程将被解除阻塞。 使用所提到的轮询解决方案确保相同的行为将需要使用锁定或原子指令(如在Interlocked
类中找到的那些)以及对可能的编译器和处理器指令重新排序/存储器障碍的良好理解。
如果您正在寻找一种简单的方法来同步多个线程,这是.NET中最简单的(如果不是最简单的)解决方案之一。 创建生产者/消费者队列非常简单:
// Simplified example. Check http://www.albahari.com/threading/part2.aspx
// for detailed explanations of this and other syncronizing constructs
private readonly AutoResetEvent _signal = new AutoResetEvent(false);
private readonly ConcurrentQueue<Something> _queue = new ConcurrentQueue<Something>();
// this method can be called by one or more threads simultaneously
// (although the order of enqueued items cannot be known if many threads are competing)
void ProduceItem(Something s)
{
_queue.Enqueue(s); // enqueue item for processing
_signal.Set(); // signal the consumer thread if it's waiting
}
// this loop should be running on a separate thread.
void ConsumerLoop()
{
while (!_ending)
{
// block until producer signals us
_signal.WaitOne();
// process whatever is enqueued
Something s = null;
while (!_ending && _concurrentQueue.TryDequeue(out s))
{
Process(s);
}
}
}
您需要注意的一件事是,对Set
多次连续调用不一定会多次向WaitOne
发出信号。 在此示例中,多个生成器可能会触发Set
方法,但是在上下文切换发生并且ConsumerLoop
继续之前可能需要几毫秒,这意味着只有一个Set
将被有效地处理。
另一个线程正在使用event_2.Wait()等待事件,并从线程调用.Set(),等待线程将继续执行。
如果是这样,它基本上做到了:
AutoResetEventState =!AutoResetEventState
?
除此之外,它还将EventWaitHandle
设置为允许一个或多个线程继续进行的信令状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.