13

I have a console application, and I want it to wait till some event is raised. But it executes the code and exits:

static void Main(string[] args)
{
    var someObjectInstance = new SomeObject();
    someObjectInstance.SomeEvent += SomeEventHandler;
}

static void SomeEventHandler()
{
    //Some logic
}

I want to make my application behave like a Windows application where

Application.Run(new Form1());

is called and the message loop is run.

But I don't need neither a message loop nor any form. So it looks like overhead. Is there a more light-weight way to achieve my goal?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
SiberianGuy
  • 24,674
  • 56
  • 152
  • 266
  • 2
    What *aspect* of the behaviour of a Windows Forms app are you really looking for? What's going to raise that event? – Jon Skeet Aug 02 '10 at 17:43
  • 1
    I want it to be possible to wait for some event and then exit the application manually. WinForms implements similar behaviour by Application.Run method. It's a ConnectionLost event generated by IPC class based on sockets. – SiberianGuy Aug 02 '10 at 19:27

3 Answers3

23

First off, unless SomeObject is going to raise the event on a separate thread, this won't work without some form of processing in SomeObject. If it's designed that way, however, this is fairly straightforward.

A very efficient way of handling this is to just wait on a WaitHandle:

private static ManualResetEvent waitHandle = new ManualResetEvent(false);
static void Main(string[] args)
{
    var someObjectInstance = new SomeObject();
    someObjectInstance.SomeEvent += SomeEventHandler;
    waitHandle.WaitOne(); // Will block until event occurs
}

static void SomeEventHandler()
{
    //some logic
    waitHandle.Set(); // Will allow Main() to continue, exiting the program
}
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
3

Add

Console.ReadLine(); after you attach your eventhandler.

For example..

class Program
{
    static void Main(string[] args)
    {
        System.IO.FileSystemWatcher watcher = new System.IO.FileSystemWatcher(@"c:\", "*.txt");
        watcher.Created += new System.IO.FileSystemEventHandler(watcher_Created);
        watcher.EnableRaisingEvents = true;
        Console.ReadLine();
    }

    static void watcher_Created(object sender, System.IO.FileSystemEventArgs e)
    {
        Console.WriteLine(string.Format("{0} was created at {1:hh:mm:ss}", e.FullPath, DateTime.Now));
    }
}
Greg Bogumil
  • 1,903
  • 15
  • 23
  • 1
    That will just cause the Console application to hang forever, unless somebody types into the Console... Not sure that's the appropriate behavior here, since it has nothing to do with waiting for an (external) event. – Reed Copsey Aug 02 '10 at 17:47
  • 1
    in production I would use a service for this specific example. But this does work just fine. – Greg Bogumil Aug 02 '10 at 18:14
-1

EDIT: Sadly, I was incorrect and this won't work, because Application is not defined for a console application (Thank you, Reed Copsey).

This should do the trick, although depending on the sleeptime you choose you could end up hogging the CPU. I feel like there must be a safer way to do this?

while (true)
{
    Application.DoEvents();
    Thread.Sleep(this.SleepTime);
}

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
WillfulWizard
  • 5,340
  • 2
  • 19
  • 15
  • 1
    This is only going to work if you have a Windows Forms message pump, which should never be in a Console application... "Application" is defined on Windows Forms applications only. Also, sleeping like this is probably not the best approach, in any case. – Reed Copsey Aug 02 '10 at 17:46