繁体   English   中英

AutoResetEvent.Set()有什么作用?

[英]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属性,您只需切换)是:

  1. 信令:将在e.WaitOne()处阻止的线程将发出信号 ,其中一个将继续。 如果你想在没有同步原语的情况下自己这样做,你必须实现某种轮询; “阻塞”线程必须定期轮询bool (或者说, int )字段以检查它是否已更改并允许继续。 如果不出意外,这会不必要地消耗cpu周期并且会有延迟(取决于你的轮询间隔)。

  2. 原子性:如果多个线程在等待,您可以保证只有一个线程将被解除阻塞。 使用所提到的轮询解决方案确保相同的行为将需要使用锁定或原子指令(如在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM