AutoResetEvent累积Sets()

时间:2018-07-31 13:36:23

标签: c# .net multithreading synchronization

我已将此代码编写为概念证明,以检查我正在尝试的当前项目的问题。

var sleeper = new AutoResetEvent(false);

        sleeper.Set();
        sleeper.Set();
        sleeper.Set();

        var ix = 0;
        while(true) {
            sleeper.WaitOne();
            Console.Write(ix++);
        }

令人惊讶的是(至少对我来说)我没有得到预期的结果。 我希望在控制台中打印出012,但只打印0

  • 我误会什么?
  • 哪种方法可能是解决此问题并获得预期结果的最佳方法?

1 个答案:

答案 0 :(得分:0)

  1. 您的代码的实际输出为0

  2. AutoResetEvent没有内存,无论是否发出信号。信号发出后,您正在等待它。您的情况下的事件顺序:

    • 创建AutoResetEvent(状态= 0)
    • 信号AutoResetEvent(状态= 1)
    • 信号AutoResetEvent(状态= 1)
    • 信号AutoResetEvent(状态= 1)
    • 开始等待事件(处理当前信号状态1并将其切换为0)
    • 继续等待事件

如msdn AutoResetEvent description

中所述
  

此外,如果在没有等待线程的情况下调用Set,并且   AutoResetEvent已发出信号,该调用无效。

  1. 要观察所需的行为,您需要第二个线程(因为为线程间通信创建了AutoResetEvent)。

类似的事情应该对您有用

private static AutoResetEvent sleeper;

static void Main()
{
    sleeper = new AutoResetEvent(false);

    Thread t = new Thread(ThreadProc);
    t.Start();

    var ix = 0;
    while(true) 
    {
        sleeper.WaitOne();
        Console.Write(ix++);
    }
}

static void ThreadProc()
{
    Thread.Sleep(1000);
    sleeper.Set();
    Thread.Sleep(1000);
    sleeper.Set();
    Thread.Sleep(1000);
    sleeper.Set();
}
  1. 请注意,AutoResetEvent不会保证将针对以下代码处理3个事件

    sleeper.Set();
    sleeper.Set();
    sleeper.Set();
    

如其“ description”中所述 因此,Thread.Sleep(1000)位。

  

不能保证每次调用Set方法都会释放一个   线。如果两个电话距离太近,那么第二个电话   发生在释放线程之前,仅释放一个线程。   好像第二个电话没有发生。