4

I know this might be strange but I have a timer and I have an event handler for Elapsed event that writes on Console, but when I start the application, the timer start properly, the event fire properly, too. However, the result doesn't show in console except after I press a button, which made me put two Console.ReadKey() so the application won't terminate.

Here is the code in Program.cs:

    static void Main(string[] args)
    {
        Timer timer = new Timer(100);
        timer.Elapsed += new ElapsedEventHandler(WriteOnConsole);
        timer.Start();
        Console.ReadKey();
        Console.ReadKey();
    }

    static void WriteOnConsole(object source, ElapsedEventArgs e)
    {
        Console.WriteLine("A B C D");
    }

Please inform me if I haven't mentioned enough information.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443

3 Answers3

8

The ReadKey() blocks the WriteLine(). After you pressed one key, the first ReadKey is finished and the pending writes to the console are flushed.

As this obviously only is a small sample to demonstrate the problem it is hard to suggest a better alternative.

One could be to use some sort of wait handle to exit the application only when a certain condition is met.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • 1
    But only the first one. And only if you haven't already written to it. I think there's something weird in the way the console is initialized, basically. – Jon Skeet Mar 01 '13 at 12:56
  • 1
    @JonSkeet: Which "first one" do you mean? The first `ReadKey` or the first `WriteLine`? – Daniel Hilgarth Mar 01 '13 at 12:57
  • Coincidentally, I think this has the same cause as the thing I asked about yesterday: http://stackoverflow.com/questions/15143931/strange-behaviour-of-console-readkey-with-multithreading – Matthew Watson Mar 01 '13 at 12:57
  • @DanielHilgarth: The first `ReadKey`. Note how the second `ReadKey` call *doesn't* block anything. – Jon Skeet Mar 01 '13 at 12:58
  • @JonSkeet The first `ReadKey`doesn't block anything either on my machine. – ken2k Mar 01 '13 at 12:59
  • Thank you Daniel, thank you Eivind. I'm still a beginner in C#, I used `Console.ReadLine()` which I never thought I'd use it for that purpose – Imad Nabil Alnatsheh Mar 01 '13 at 13:00
  • @ken2k: Indeed, on mine neither. It outputs right away. Strange. – Daniel Hilgarth Mar 01 '13 at 13:00
  • @Jon Skeet: What do you mean the second call to ReadKey _doesn't_ block anything ? Do you mean to say that it isn't a blocking call (which returns only after the console received a key press) ? Because it is... – Eduard Dumitru Mar 01 '13 at 13:01
  • @EduardDumitru: It's a blocking call, but it doesn't prevent another thread from writing output. – Jon Skeet Mar 01 '13 at 13:04
  • @JonSkeet: Oh. sorry.. I misunderstood. Of course it doesn't. You know what I thought you meant... Dangerously homonymic terms ended up in the same little package :) `Console.ReadKey` – Eduard Dumitru Mar 01 '13 at 13:08
  • @EduardDumitru: The point is that the "of course" isn't really an "of course" because when it's broken, the first `ReadKey` *does* block the `WriteLine` in the other thread. – Jon Skeet Mar 01 '13 at 13:09
3

Try writing an empty string from the 1st thread, before anything else, thus initializing the Console:

static void Main(string[] args)
{
    Console.Write(string.Empty);
    Timer timer = new Timer(100);
    timer.Elapsed += new ElapsedEventHandler(WriteOnConsole);
    timer.Start();
    Console.ReadKey();
    Console.ReadKey();
}

static void WriteOnConsole(object source, ElapsedEventArgs e)
{
    Console.WriteLine("A B C D");
}
Eduard Dumitru
  • 3,242
  • 17
  • 31
2

I've seen this in another question - you don't even need a timer, just any two threads where one thread is reading from the console and another is writing.

It looks like the initialization for Console is somewhat broken - the first call to it will effectively take out a lock until it completes, preventing any other console access.

If you write:

Console.WriteLine("Starting");

at the start of your code, all will be fine, for example. It's not like ReadKey (or any other read operation) blocks all console output in general - it's just in the first call.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    I can't reproduce: the OP's code works fine on my machine (edit: I mean it outputs directly to the console without the need to press a key) – ken2k Mar 01 '13 at 13:00
  • 1
    This is a race condition, and it seems to only occur on some systems. – Matthew Watson Mar 01 '13 at 13:04