0

I have a program that calls a Filewatcher function, like this

Main()  
{  
    watch();        
    console.Readkey();
}

I have the console.readkey at the end because I don't want the console to display 'Press any key to continue' while the file is being watched for changes. Now, if a change is detected, another function gets triggered off, which does its thing, and eventually calls main again, which once again stops at console.readkey.

At this point, I am experiencing some weird problems like the program requires two key inputs to continue. I'm guessing thats because the console.readkey from before is still waiting for an input, so the first input goes there, and then the second input goes to the second console.readkey.

So, my question is, the first time when the filewatcher gets triggered, can i, via code, feed something to the console.readkey, thats waiting for a user input?

3 Answers 3

1

Console.ReadKey will block the program until you press a key (at which point it will read that and return).

It sounds like you, in this situation, need to change your logic to just loop indefinitely (or until some other condition is reached). Instead of using Console.ReadKey to prevent the application from ending, you should consider re-writing it like:

bool exitProgram = false;
AutoResetEvent resetEvent = new AutoResetEvent();

void Main()
{
    while (!exitProgram)
    {
        Watch(); // Starts FileSystemWatcher
        resetEvent.WaitOne();
    }
}

void WorkFinished() // Call at the end of FileSystemWatcher's event handler
{
     resetEvent.Set(); // This "reschedules" the watcher...
}

This will make the program run "forever", until you set exitProgram to true, at which point it will exit normally. The "watch" will not get called continually, since resetEvent will block indefinitely. When your "work" finishes (after the FileSystemWatcher event handler completes), call resetEvent.Set(). This will cause the loop to repeat one more time, re-triggering your watch code.

It works by using an AutoResetEvent to prevent the watcher from "rewatching" the same file repeatedly.

Sign up to request clarification or add additional context in comments.

4 Comments

But in this case, unless I set exitProgram to true, the watcher function will get called infinitely. I just want to call the watcher function once, and let it run in the background watching for changes. Should a change be found, I stop the watcher, make some changes to the file and want to restart the watcher.
PS - when the watcher function detects a change it calls the OnChange method I have written. I cannot call the watcher function from that method itself because to make the changes necessary I need to access Main again
@xbonez: I understand now - A loop is still the right way to go. I rewrote my answer to explain how you can make this work with a loop + AutoResetEvent.
+1 Good answer (and simpler than my suggestion of importing Winforms). :)
1

The structure of your Console application should be changed to use a WaitHandle and Ctrl+C to exit the program. The basic structure of such a program is shown below. It should be trivial to convert to C#.

Module modMain

    Public shutdown As New Threading.ManualResetEvent(False)

    Public Sub FileCreated(ByVal sender As Object, ByVal e As IO.FileSystemEventArgs)
        Console.WriteLine("Created: " & e.FullPath)
    End Sub

    Public Sub FileChanged(ByVal sender As Object, ByVal e As IO.FileSystemEventArgs)
        Console.WriteLine("Changed: " & e.FullPath)
    End Sub

    Public Sub FileDeleted(ByVal sender As Object, ByVal e As IO.FileSystemEventArgs)
        Console.WriteLine("Deleted: " & e.FullPath)
    End Sub

    Public Sub FileRenamed(ByVal sender As Object, ByVal e As IO.FileSystemEventArgs)
        Console.WriteLine("Renamed: " & e.FullPath)
    End Sub

    Public Sub CancelKeyHandler(ByVal sender As Object, ByVal e As ConsoleCancelEventArgs)
        e.Cancel = True
        shutdown.Set()
    End Sub

    Sub Main()

        Dim fsw As New System.IO.FileSystemWatcher

        Try

            AddHandler Console.CancelKeyPress, AddressOf CancelKeyHandler

            ' Do your work here 
            ' press Ctrl+C to exit 
            fsw = New System.IO.FileSystemWatcher("c:\path")
            fsw.Filter = "*.*"
            fsw.NotifyFilter = (IO.NotifyFilters.Attributes Or IO.NotifyFilters.CreationTime Or IO.NotifyFilters.DirectoryName Or _
                                IO.NotifyFilters.FileName Or IO.NotifyFilters.LastAccess Or IO.NotifyFilters.LastWrite Or _
                                IO.NotifyFilters.Security Or IO.NotifyFilters.Size)
            AddHandler fsw.Created, AddressOf FileCreated
            AddHandler fsw.Changed, AddressOf FileChanged
            AddHandler fsw.Deleted, AddressOf FileDeleted
            AddHandler fsw.Renamed, AddressOf FileRenamed
            fsw.EnableRaisingEvents = True

            shutdown.WaitOne()

        Catch ex As Exception
            Console.WriteLine(ex.ToString())
        Finally
            If fsw IsNot Nothing Then fsw.Dispose()
        End Try

    End Sub

End Module

2 Comments

This doesn't show how to "reschedule" the FileSystemWatcher, though, as it will block forever...
The FileSystemWatcher runs in its own thread. Therefore the main thread should block while the FileSystemWatcher dispatches and handles events. Of course, the FileSystemWatcher can be used synchronously with the 'WaitForChanged' method.
0

Reading from this question and here, I think you need to refactor your code and borrow a message loop from Winforms to keep your program alive.

Add a reference to System.Windows.Forms.dll. In your main method, start your watcher. Then call Application.Run() Don't worry, your app can still use the console, etc, Run() will just start a message loop and prevent your program continuing to the end of the main method.

Then refactor your code from the previous question so it doesn't call Main() again.

Whenever you want to stop your application, call Application.Exit().

5 Comments

I want my code to keep looking for changes. So after the first change is detected and the OnChange method is triggered, I'd have to call the Filewatcher method function again. This would set the filewatcher to look fr changes again, and the cursor would inevitably reach the end of main again displaying 'Press any key...' which is what I want to avoid
I don't think that's the problem - I think the problem is more that the OP wants an infinite (or at least repeating) loop, but doesn't know how to write one...
LOL...I know how to write a loop, but I don't want to call the watcher function infinitely on loop. I want to call it once, and then have the background thread watching. I want it to be called again only in the instance that a change in the file is detected (because when the change is detected, I stop the watcher, make some changes to the file, and want to start the watcher again).
@xbonez: Are you calling Main() again only to start the watcher again?
@Reed: Yes. I think that's it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.