Ayush
Ayush

Reputation: 42450

Feed input to Console.ReadKey

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?

Upvotes: 0

Views: 2896

Answers (3)

Pineapple
Pineapple

Reputation: 41

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

Upvotes: 1

Reed Copsey
Reed Copsey

Reputation: 564891

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.

Upvotes: 1

Zach Johnson
Zach Johnson

Reputation: 24232

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().

Upvotes: 0

Related Questions