Question

I am trying to understand the question (and, respectively, the answers to it):

with attached below code

The comment in code tells:

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

But I do not see how and why any of the threads can be blocked indefinitely...
I tried to run the code and I cpuld not observer any indefinite blocking...

What do I miss in this question (and respective answers)?

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

Update:
I was launching this code as:

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

  }
}

And I do not observe any indefinite blocking.

Here is the output of having run the code:

Doing stuff...
222222222222
1111111111
Stuff done.

How should I run (update, change, increment) the code in order to reproduce the discussed topic (of having one the threads being blocked indefinitely)?

Was it helpful?

Solution 3

Here is eventual code to reproduce the problem.

Note that autoEvent cannot be local in order to be seen in other metods and it should be static in order to be used from static Main() and Test() methods and thereafter "used" from it static methods:

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

OTHER TIPS

From MSDN

  • AutoResetEvent remains signaled until a single waiting thread is released.

The AutoResetEvent works as turnstile. One call of Set releases only one thread.

The ARE is a strange beast. If you read the MSDN entry for it, you will find that, if signaled once while more than one thread is waiting, it will release only one waiting thread. If, however, no threads are waiting when it's signaled, it does not keep a count of the signal and it is 'lost'.

It's a strange crossbreed between a manual reset event and a semaphore. TBH, I find it less useful than either :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top