2
System.Timers.Timer timer= new System.Timers.Timer(1);
            timer.AutoReset = true;
            timer.Elapsed += (s, e) =>
            {
                Console.WriteLine("fired");
            };
timer.Start();

The event is consistently fired in debug mode, and consistently not fired in release mode. I tried disabling compiler optimizations, but it didn't help.

I am trying to run this in an asp.net mvc application .net 4.6 framework

blenddd
  • 345
  • 1
  • 6
  • 15
  • 1
    Is it possible that `Console.WriteLine` isn't working in Release mode? I ask because I've had problems where Console.WriteLine logs to the VS Output window in one configuration but not in another (never figured out why). Might be worth checking before you blame the timer. – adv12 May 16 '16 at 18:58
  • Are you sure the block of code is even run to start the timer in release mode? Also, you tagged your question asp.net, perhaps your app domain is getting shut down? – Scott Chamberlain May 16 '16 at 19:05
  • How can I be sure my timer is being run? I know it's created with the correct interval. Also, I am not sure if this is related to asp or not, but I thought extra info will not hurt. Would it make sense that my app domain is being shut down in release but not in debug? – blenddd May 16 '16 at 19:17
  • are you using compiler directives on your code? – Zinov May 16 '16 at 19:35
  • not sure what exactly you mean here, but I tried adding an annotation to prevent compile time optimizations, and it did not help – blenddd May 16 '16 at 19:41
  • What are you trying to accomplish? Do you just want to see how the timer works, or do actually need something to occur at intervals in your web application? If it's the latter then there are a number of answers suggesting how to do that. – Scott Hannen May 16 '16 at 19:51
  • can you suggest ways to do that in a web application? – blenddd May 17 '16 at 05:57

3 Answers3

4

Your timer is probably fine, but your method of testing that is flawed.

Data written to Console.WriteLine in release mode in ASP.NET applications is lost. See the answer to this question: Where does Console.WriteLine go in ASP.net production environment?

If you really want to use Console.WriteLine, you can use Console.SetOut to redirect the output to a file.

Also, make sure your timer object is not declared inside a method since it will be destroyed as soon as the method completes.

Community
  • 1
  • 1
Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84
  • I tried different stuff, including throwing an exception...nothing happens in release build, and debug still works fine – blenddd May 16 '16 at 19:14
  • 1
    The timer's Elapsed event runs in a different thread. Nothing is there to catch the exception, so the thread will just die, but not the whole application. The unhandled exception *might* show up in the Windows Application Event Log. – Gabriel Luci May 16 '16 at 19:16
  • I have this in the application start, so the application should throw an exception, which does happen in the debug mode, but not in the release – blenddd May 16 '16 at 19:18
  • Some more context might help too. Is all of this code in one method? Your `timer` object needs to be in a context where it will survive long enough to fire. – Gabriel Luci May 16 '16 at 19:19
  • my timer is a class variable, the class has a lifetime as long as he application is running – blenddd May 16 '16 at 19:24
  • Try using Console.SetOut then, so that Console.WriteLine writes to a file. But it needs to be a file that the application has permissions to write to. – Gabriel Luci May 16 '16 at 19:30
  • Gabriel, you were right. I tried changing a bool in the elapsed event, and throwing an exception depending on the bool value and that worked! – blenddd May 16 '16 at 20:00
  • Awesome. Glad you figured it out. – Gabriel Luci May 17 '16 at 13:01
2

Your timer is set to 1ms. That could produce some unpredictable results because the "resolution" - the intervals at which the timer is checked - is typically around 15ms. If you're just trying to test the behavior of a timer then I'd increase it to maybe 20ms or more.

I tested this. A 1ms interval running for 500ms consistently elapsed 32 times - roughly once every 15ms. This was the same in debug and release. No exceptions were thrown.

Instead of writing to the console I'd recommend adding items to a globally accessible ConcurrentQueue when the timer elapses (since this is just for testing/experimentation.)

Then on a web page you could output the contents of the queue. You might want to stop the timer first so it doesn't keep pumping items into the queue. (Or just use a longer interval.)

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
1

Hope the following solution helps!

Problem:

The following code always works as expected by showing the current clock time.

 class Program
 {
        static void TimerProcedure(object param)
        {
            Console.Clear();
            Console.WriteLine(DateTime.Now.TimeOfDay);

            GC.Collect();

        }

        static void Main(string[] args)
        {
            Console.Title = "Desktop Clock";
            Console.SetWindowSize(20, 2);
            Timer timer = new Timer(TimerProcedure, null,
                TimeSpan.Zero, TimeSpan.FromSeconds(1));
            Console.ReadLine();
        }
    }

However, if you run the same code in release mode, it shows current time only for the first time but it never updates after that.

Solution

A simple tweak by adding GC.KeepAlive(object) will make it work in Release mode also as expected. Refer to code below.

class Program
    {
        static void TimerProcedure(object param)
        {
            Console.Clear();
            Console.WriteLine(DateTime.Now.TimeOfDay);
            #region Hidden
            GC.Collect();
            #endregion
        }

        static void Main(string[] args)
        {
            Console.Title = "Desktop Clock";
            Console.SetWindowSize(20, 2);
            Timer timer = new Timer(TimerProcedure, null,
                TimeSpan.Zero, TimeSpan.FromSeconds(1));
            Console.ReadLine();
            GC.KeepAlive(timer);
        }
    }

Coming to your specific problem, verify if the scope of timer variable is local to a method. If that is true, you can keep it alive as shown above.

Alternate solution: is making timer a class level static variable