简体   繁体   English

AutoResetEvent.Set()有什么作用?

[英]What does AutoResetEvent.Set() do ?

If I do this : 如果我这样做:

private static System.Threading.AutoResetEvent event_2 = new System.Threading.AutoResetEvent(false);

And then in Main thread I do : 然后在主线程中我做:

event_2.Set();

It changes the state from false to true ? 它将状态从false更改为true

If so , it basically does : 如果是这样,它基本上做到了:

AutoResetEventState = !AutoResetEventState 

?

It sets the state to one that allows threads to continue execution if they Wait() on it. 它将状态设置为允许线程在Wait()上继续执行的状态。

If there are any threads already waiting, then one will be allowed to progress and the state will immediately be set to not set, so all other threads will continue to block. 如果有任何线程已经在等待,那么将允许一个线程进行并且状态将立即设置为未设置,因此所有其他线程将继续阻塞。

If there are no threads currently waiting then the first to wait will immediately be allowed through, but subsequent threads will block. 如果当前没有线程正在等待,那么将立即允许第一个等待,但后续线程将阻塞。

The same general mechanism is shared by other EventWaitHandle -derived classes, but the automatic resetting upon a thread being allowed to progress is different to ManualResetEvent , hence the names. 其他EventWaitHandle派生的类共享相同的通用机制,但允许进行的线程的自动重置与ManualResetEvent不同,因此名称也不同。

The initial state is signalled (allowing threads to progress) if true is passed to the constructor, and not signalled if false is passed, so passing true is the same as if you'd called Set() immediately after construction while passing false is conversely the same as if you'd called Reset() . 如果将true传递给构造函数,则初始状态发出信号(允许线程进行),如果传递false则不发出信号,因此传递true与构造后立即调用Set()相同,而传递false则相反就像你调用Reset()

A thread waits for a signal by calling WaitOne on the AutoResetEvent. 线程通过在AutoResetEvent上调用WaitOne来等待信号。 If the AutoResetEvent is in the non-signaled state, the thread blocks, waiting for the thread that currently controls the resource to signal that the resource is available by calling Set. 如果AutoResetEvent处于非信号状态,则线程阻塞,等待当前控制资源的线程通过调用Set来指示资源可用。

Calling Set signals AutoResetEvent to release a waiting thread. 调用Set信号AutoResetEvent释放等待线程。 AutoResetEvent remains signaled until a single waiting thread is released, and then automatically returns to the non-signaled state. AutoResetEvent保持信号状态,直到释放单个等待线程,然后自动返回到非信号状态。 If no threads are waiting, the state remains signaled indefinitely. 如果没有线程在等待,则状态将无限期地发出信号。

To add to other answers, the reason you need a this (instead of having a bool property you would simply toggle) is: 要添加到其他答案,您需要这个的原因(而不是具有bool属性,您只需切换)是:

  1. Signalling: threads which are blocked at e.WaitOne() will be signalled , and one of them will continue. 信令:将在e.WaitOne()处阻止的线程将发出信号 ,其中一个将继续。 If you wanted to do this yourself without synchronization primitives, you would have to implement some sort of polling; 如果你想在没有同步原语的情况下自己这样做,你必须实现某种轮询; a "blocking" thread would have to poll a bool (or, say, int ) field in regular intervals to check if it has changed and it is allowed to continue. “阻塞”线程必须定期轮询bool (或者说, int )字段以检查它是否已更改并允许继续。 If nothing else, this would unnecessarily consume cpu cycles and would have a delay (depending on your polling interval). 如果不出意外,这会不必要地消耗cpu周期并且会有延迟(取决于你的轮询间隔)。

  2. Atomicity: if multiple threads are waiting, you have a guarantee only one will be unblocked. 原子性:如果多个线程在等待,您可以保证只有一个线程将被解除阻塞。 Ensuring the same behavior using the mentioned polling solution would require use of locking or atomic instructions (like the ones found in Interlocked class) and good understanding of possible compiler and processor instruction reordering/memory barriers. 使用所提到的轮询解决方案确保相同的行为将需要使用锁定或原子指令(如在Interlocked类中找到的那些)以及对可能的编译器和处理器指令重新排序/存储器障碍的良好理解。

If you are looking for a simple way to synchronize multiple threads, this is one of the simplest (if not the simplest) solutions in .NET. 如果您正在寻找一种简单的方法来同步多个线程,这是.NET中最简单的(如果不是最简单的)解决方案之一。 Creating a producer/consumer queue is remarkably simple: 创建生产者/消费者队列非常简单:

// 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);
        }
    }
}

One thing you need to keep in mind though is that multiple successive calls to Set won't necessarily signal WaitOne multiple times. 您需要注意的一件事是,对Set多次连续调用不一定会多次向WaitOne发出信号。 In this example, several producers might fire the Set method, but it may take a couple of milliseconds until the context switch happens and ConsumerLoop continues, meaning that only a single Set will effectively get processed. 在此示例中,多个生成器可能会触发Set方法,但是在上下文切换发生并且ConsumerLoop继续之前可能需要几毫秒,这意味着只有一个Set将被有效地处理。

另一个线程正在使用event_2.Wait()等待事件,并从线程调用.Set(),等待线程将继续执行。

If so , it basically does : 如果是这样,它基本上做到了:

AutoResetEventState = !AutoResetEventState AutoResetEventState =!AutoResetEventState

?

In addition to that it also sets the EventWaitHandle to signaling state allowing one or more thread to proceed. 除此之外,它还将EventWaitHandle设置为允许一个或多个线程继续进行的信令状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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