2

I'm creating small applciaiton that will be used to detect some changes on system. It is used by admins so it doesn't have to nice and "perfect".

I have loop that checks for changes. I want to check for changes once every 10 seconds. But I would like to be able to "cancel" that thread.sleep with button press to get out of that loop.

    static async void Main(string[] args)
    {
        Console.WriteLine("Logger started. Press any key to exit application.\n");

        while (!Console.KeyAvailable) //Works. but only every 10 seconds
        {
            CheckForAndLogChanges();
            Thread.Sleep(10000);
        }

        //Rest of code that I want to execute right after pressing key without waiting 10s.

    }

Update: I like answer with timer.

This is what I also came up with:

    static void Main(string[] args)
    {
        Console.WriteLine("Logger started. Press any key to exit application.\n");

        var backgroutTask = new Task(WorkerThread, TaskCreationOptions.LongRunning);
        backgroutTask.Start();

        Console.ReadKey(false);
    }

    static async void WorkerThread()
    {
        while (true)
        {
            CheckForAndLogChanges();
            await Task.Delay(100);
        }
    }

What is the adventage of using timer over this task?

Hooch
  • 28,817
  • 29
  • 102
  • 161
  • This is rather trivial, just sleep for 100 msec and count to a 100 before you CheckForAndLogChanges(). It doesn't have to perfect after all. – Hans Passant Sep 13 '14 at 14:37
  • @HansPassant For the sake of learning I want this trivial program to be as perfect as anything can get. I want to be writing good code. Even for that simple tasks. – Hooch Sep 13 '14 at 15:07
  • Trivial code is good code, it has far fewer bugs and is much easier to maintain. If you want to learn about the numerous ways that Timer can make your life miserable, and it is about as miserable a class you could possibly find the framework, then surely you don't need our help. – Hans Passant Sep 13 '14 at 15:11
  • @HansPassant I understand your view. Just that simple program isn't something that will be maintained or weidly used. It is just small tool that is more for me to check new thing and learn a little bit of .net. I know that writing "perfect" code is not always needed. But I just wanted to experiment. If I learn it today. I will use it in future in bigger applications. – Hooch Sep 13 '14 at 15:14
  • @Hooch I deleted my answer. I believe that `Timer` could be quite OK in such case. But there are different timers, see e.g. http://stackoverflow.com/q/1416803 (there are even more). There are different ways to synchronize with the main thread and different ways to wait for possible running operations to terminate. I have no time to extend the answer accordingly, and just did not want to keep it half way, since it might be misleading for someone. – AlexD Sep 14 '14 at 01:13

1 Answers1

1

Use a ManualResetEvent:

ManualResetEvent mre=new ManualResetEvent(false);
//......
var signalled=mre.WaitOne(TimeSpan.FromSeconds(8));
if(!signalled)
{
    //timeout occurred
}

elsewhere (before the 8 seconds is up):

mre.Set(); //unfreezes paused Thread and causes signalled==true

and allow the unblocked thread to terminate gracefully. Thread.Abort is evil and should be avoided.

Community
  • 1
  • 1
Agent_Spock
  • 1,107
  • 2
  • 16
  • 44
  • From all above. I think that Timers or Tasks will be better option. Your code is working, but isn't ManualResetEvent just a bit overkill for what I want to do? – Hooch Sep 13 '14 at 15:10