tags:

views:

653

answers:

5

I have an app it sets up a FileSystemWatcher. It should run indefinitely.

What is the best way to have it run in an idle loop?

I'm currently doing

FileSystemWatcher watch = ... //setup the watcher
watch.EnableRaisingEvents = true;
while (true) 
{
    Thread.Sleep(int.MaxValue);
}

which seems to work (ie, captures the events and doesn't use up a core in a busy loop).

Any other idiom? Any problem with this approach?

+2  A: 

Thread.Sleep() will do what you want. But basically you should block using an OS method that will wake upon your desired strategy. Eg. a Console.ReadLine() or upon a mutex which is hit by your event handler to go away.

You shouldn't have to kill your app to make it shut.

If you embed the code on a form then at least the form can be killed nicely, with a reasonable OS load when you aren't using it.

Spence
+1 for the possibility of terminating without killing
Frederik Gheysels
A: 

I do not understand ... Why do you want and idle loop ? Do you want to have your application run indefinitely ?

Then, why don't you create a Windows Service, or an application that can be run in the system tray ?

Then, what I would do is create a class which just does this:

public class Foo
{
   private FileSystemWatcher _fs;

   private volatile bool _stopped = false;

   public Foo()
   {
       _fs = new FileSystemWatcher();
       ...
   }

   public void Start()
   {
       _stopped = false;
       Thread t = new Thread (new ThreadStart(DoWork));
       t.Start();
   }

   private void DoWork()
   {
       while( !_stopped )
       {
           Thread.Sleep(1);
       }
   }

   public void Stop()
   {
       _stopped = true;
   }

}
Frederik Gheysels
A service is out of the question because it cannot require admin privileges to install. System tray is problematic because there is another process which lauches this console app and captures its output.
Vinko Vrsalovic
+2  A: 

If you mark the thread where this loop is running as a background thread (Thread.IsBackground property) then it should work fine (the program will exit when all non background threads terminate)

chris166
Won't that make it terminate when there are no events for a while?
Vinko Vrsalovic
+2  A: 

As I understood from your comment you need your application to run indefinitely and it is a console app that is lunched by another executable.

It is better to use Console.ReadLine instead of looping. or use Monitor.Wait method to block the thread indefinitely

object sync = new object();
lock(sync)
Monitor.Wait(sync);
Ahmed Said
+7  A: 

FileSystemWatcher.WaitForChanged is blocking (synchronous). There is absolutely no need for an idle loop, especially because you are handling events. Note EnableRaisingEvents defaults to true. Therefore, all you have to do is add the component to a form. There is no idle loop. There is no threading because the component takes care of that.

I understand you are using a Console Application. Therefore, you can create the following loop. Again, no need for an idle loop. The component takes care of all the details.

    Do
        Dim i As WaitForChangedResult = Me.FileSystemWatcher1.WaitForChanged(WatcherChangeTypes.All, 1000)
    Loop Until fCancel

[update] "Note EnableRaisingEvents defaults to true." As per the Microsoft source code, this is only true if the FileSystemWatcher component is dropped onto a designer. As shown below:

    /// <internalonly/>
    /// <devdoc>
    /// </devdoc>
    [Browsable(false)] 
    public override ISite Site {
        get { 
            return base.Site; 
        }
        set { 
            base.Site = value;

            // set EnableRaisingEvents to true at design time so the user
            // doesn't have to manually. We can't do this in 
            // the constructor because in code it should
            // default to false. 
            if (Site != null && Site.DesignMode) 
                EnableRaisingEvents = true;
        } 
    }

[update] Calling WaitForChanged sets EnableRaisingEvents immediately before and after the System.Threading.Monitor.Wait statements.

AMissico
Thanks for this. I accepted the other answer because it answers the actual question (good way to do an idle loop). I upvoted you, of course.
Vinko Vrsalovic
Your question is "What is the best way to have it [the FileSystemWatcher] run in an idle loop?" Therefore, the accepted answer is incorrect.
AMissico