Tuesday 9 October 2012

Using a ManualResetEvent To Stop A Console Application From Terminating


This is a quick example of how to use a ManualResetEvent to stop a console application from terminating whilst an event driven (or callback driven) asynchronous process is busy.




Basically a ManualResetEvent is waited on at the end of the main method until it is signalled to complete by one of the events:

using System;
using System.Threading;

namespace ConsoleApplicationWait
{
  class Program
  {
    static ManualResetEvent _mre = new ManualResetEvent(false);
    static EventSource _src = new EventSource();

    static void Main(string[] args)
    {
      _src.NewNumber += _src_NewNumber;
      _src.Finished += _src_Finished;

      // Starting events
      _src.Start();

      // Block main thread until signalled to continue
      Console.WriteLine("Reached the end of main method and waiting for signal...");
      _mre.WaitOne();

      Console.WriteLine("Signal received, press enter to exit...");
      Console.ReadLine();
    }

    static void _src_Finished(object sender, EventArgs e)
    {
      Console.WriteLine("Finished event received, signalling all done");

      // Signal wait handle to continue
      _mre.Set();
    }

    static void _src_NewNumber(object sender, NumberEventArgs e)
    {
      Console.WriteLine(e.Number);
    }
  }

  /// <summary>
  /// Simple number eventargs
  /// </summary>
  public class NumberEventArgs : EventArgs
  {
    public int Number { get; set; }

    public NumberEventArgs(int number)
    {
      this.Number = number;
    }
  }

  /// <summary>
  /// Class to simulate something which generates a number of events
  /// </summary>
  public class EventSource
  {
    public event EventHandler<NumberEventArgs> NewNumber;
    public event EventHandler Finished;

    public void Start()
    {
      Thread t = new Thread(new ThreadStart(() =>
        {
          for (int i = 0; i < 10; i++)
          {
            if (this.NewNumber != null)
              this.NewNumber(this, new NumberEventArgs(i));

            // 1s delays so we can see what's going on
            Thread.Sleep(1000);
          }

          if (this.Finished != null)
            this.Finished(this, new EventArgs());
        }));

      t.Start();
    }
  }
}

No comments:

Post a Comment