1

我试图理解这个问题(以及分别的答案):

附上以下代码

代码中的注释告诉:

// set the event - I thought this would mean both waiting threads are allowed to continue
// BUT thread2 runs and thread1 stays blocked indefinitely

但我不明白任何线程如何以及为什么可以无限期地阻塞......
我试图运行代码并且我没有观察到任何无限期的阻塞......

我在这个问题(以及相应的答案)中错过了什么?

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

更新:
我将此代码启动为:

using System;
using System.Threading;

namespace bothCallWaitOne
{
  class Program
  {
    static void Main(string[] args)
    {

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

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

      //Thread thread2 = new Thread(new ThreadStart(WriteSomeOtherMessageToTheConsole));
      Thread thread2 = new Thread(new ThreadStart(WriteSomeOtherMessageToTheConsole));
      thread2.Name = "222222222222";
      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?
      autoEvent.Set();
      Console.ReadLine();
    }

    static void WriteSomeMessageToTheConsole()
    {
      Console.WriteLine(Thread.CurrentThread.Name);
    }
    static void WriteSomeOtherMessageToTheConsole()
    {
      Console.WriteLine(Thread.CurrentThread.Name);
    }

  }
}

而且我没有观察到任何无限期的阻塞。

这是运行代码的输出:

Doing stuff...
222222222222
1111111111
Stuff done.

我应该如何运行(更新、更改、增加)代码以重现所讨论的主题(让一个线程被无限期阻塞)?

4

3 回答 3

1

来自MSDN

  • AutoResetEvent 保持信号状态,直到一个等待线程被释放。

AutoResetEvent 用作旋转门。一次调用只Set释放一个线程。

于 2013-03-09T08:18:45.223 回答
0

ARE是一种奇怪的野兽。如果你阅读它的 MSDN 条目,你会发现,如果在多个线程等待时发出一次信号,它只会释放一个等待线程。但是,如果在发出信号时没有线程在等待,则它不会保留信号的计数并且它会“丢失”。

这是手动重置事件和信号量之间的奇怪杂交。TBH,我发现它没有任何一个有用:)

于 2013-03-09T08:21:39.040 回答
0

这是重现问题的最终代码。

请注意,autoEvent不能是本地的,以便在其他方法中看到,它应该是静态的,以便从静态Main()Test()方法中使用,然后从它的静态方法中“使用”:

using System;
using System.Threading;

namespace bothCallWaitOne
{
  class Program
  {
    static AutoResetEvent autoEvent = new AutoResetEvent(false);
    static void Main(string[] args)
    {
      Test();
      Console.ReadLine();
    }
    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);

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

      //Thread thread2 = new Thread(new ThreadStart(WriteSomeOtherMessageToTheConsole));
      Thread thread2 = new Thread(new ThreadStart(WriteSomeOtherMessageToTheConsole));
      thread2.Name = "222222222222";
      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?
      autoEvent.Set();
    }
    static void WriteSomeMessageToTheConsole()
    {
      autoEvent.WaitOne();//Cannot relve symbol autoEvent
      while(true)
        Console.WriteLine(Thread.CurrentThread.Name+"****");
    }
    static void WriteSomeOtherMessageToTheConsole()
    {
      autoEvent.WaitOne();//Cannot relve symbol autoEvent
      while(true)
      Console.WriteLine(Thread.CurrentThread.Name);
    }
  }
}
于 2013-03-09T09:31:34.520 回答