0

假设 ThreadA 和 ThreadB 都WaitOne()在同一个 AutoResetEvent 上按此顺序调用。设置事件后,为什么释放 ThreadB 而不是 ThreadA?

我进行了一项测试,以了解当您设置多个线程正在等待的 AutoResetEvent 时会发生什么:

    private static void Test()
    {
        // two threads - waiting for the same autoreset event
        // start it unset i.e. closed i.e. anything calling WaitOne() will block
        AutoResetEvent autoEvent = new AutoResetEvent(false);

        Thread thread1 = new Thread(new ThreadStart(WriteSomeMessageToTheConsole));
        thread1.Start();  // this will now block until we set the event

        Thread thread2 = new Thread(new ThreadStart(WriteSomeOtherMessageToTheConsole));
        thread2.Start();  // this will now also block until we set the event

        // simulate some other stuff
        Console.WriteLine("Doing stuff...");
        Thread.Sleep(5000);
        Console.WriteLine("Stuff done.");

        // set the event - I thought this would mean both waiting threads are allowed to continue
        // BUT thread2 runs and thread1 stays blocked indefinitely
        // So I guess I was wrong and that Set only releases one thread in WaitOne()?
        // And why thread2 first?
        autoEvent1.Set();
    }

代码当然没用;这只是一个米老鼠的例子。这并不重要/紧急。但无论如何我有兴趣了解更多...

4

3 回答 3

2

IIRC,未指定自动重置事件释放哪个线程。正如其他人所提到的,如果要广播条件,则需要手动重置事件。如果你想释放一个确切的数字(比如 n 中的 3 个),那么你可能想要使用信号量。

如果您真的想深入了解为什么该顺序可能与您预期的不同,请查看“Windows Internals”或 Mark Russinovich 所写的任何内容。他很有可能在某处解释了执行资源的等待命令。

于 2009-04-10T00:44:21.930 回答
1

来自 MSDN

MSDN on ManualResetEvent:“在 ManualResetEvent 上调用 WaitOne 的线程将阻塞,等待信号。当控制线程完成活动时,它调用 Set 以发出等待线程可以继续的信号。 所有等待线程都被释放。

但是对于 AutoResetEvent,MSDN 说:“调用 Set 向 AutoResetEvent 发出信号以释放等待线程。AutoResetEvent 保持信号状态,直到 释放单个等待线程,然后自动返回到非信号状态。如果没有线程在等待,则状态无限期地保持信号状态。

"

于 2009-04-10T00:36:53.663 回答
0

AutoResetEvent上,Set 只释放一个线程。您应该使用ManualResetEvent来释放多个等待线程。

于 2009-04-10T00:17:35.767 回答