7

如果我这样做:

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

然后在主线程中我做:

event_2.Set();

它将状态从 更改falsetrue?

如果是这样,它基本上是:

AutoResetEventState = !AutoResetEventState 

?

4

5 回答 5

9

它将状态设置为允许线程在其Wait()上继续执行的状态。

如果有任何线程已经在等待,那么将允许其中一个线程继续进行并且状态将立即设置为未设置,因此所有其他线程将继续阻塞。

如果当前没有线程在等待,那么第一个等待的线程将立即被允许通过,但后续线程将阻塞。

其他派生类共享相同的通用机制EventWaitHandle,但是允许线程进行时的自动重置与 不同ManualResetEvent,因此名称不同。

如果传递给构造函数,则初始状态会发出信号(允许线程继续进行),如果true传递则不会发出信号false,因此传递与您在构造后立即true调用相同,而传递则与您相反称为。Set()falseReset()

于 2015-10-09T12:14:53.863 回答
4

要添加到其他答案,您需要 this (而不是拥有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得到有效处理。

于 2015-10-09T23:31:05.753 回答
2

线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。如果 AutoResetEvent 处于非信号状态,则线程阻塞,等待当前控制资源的线程通过调用 Set 发出资源可用的信号。

调用 Set 发出 AutoResetEvent 信号以释放等待线程。AutoResetEvent 保持有信号状态,直到释放单个等待线程,然后自动返回到无信号状态。如果没有线程在等待,则状态会无限期地保持信号状态。

于 2015-10-09T11:43:47.930 回答
0

如果是这样,它基本上是:

AutoResetEventState = !AutoResetEventState

?

除此之外,它还设置了EventWaitHandle信号状态,允许一个或多个线程继续进行。

于 2015-10-09T12:04:55.150 回答
0

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

于 2015-10-09T11:44:20.013 回答