将输入输入到Console.ReadKey

时间:2010-09-17 20:18:44

标签: c#

我有一个调用Filewatcher函数的程序,比如这个

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

我最后有console.readkey,因为我不希望控制台在监视文件进行更改时显示“按任意键继续”。现在,如果检测到一个更改,另一个函数会被触发关闭,这会完成它的工作,并最终再次调用main,它再次在console.readkey处停止。

此时,我遇到了一些奇怪的问题,例如程序需要两个关键输入才能继续。我猜那是因为之前的console.readkey仍在等待输入,所以第一个输入进入那里,然后第二个输入进入第二个console.readkey。

所以,我的问题是,第一次触发filewatcher时,我可以通过代码向console.readkey提供一些内容,等待用户输入吗?

3 个答案:

答案 0 :(得分:1)

Console.ReadKey将阻止该程序,直到您按下一个键(此时它将读取并返回)。

听起来,在这种情况下,你需要将你的逻辑改为无限循环(或者直到达到其他条件)。您应该考虑重写它,而不是使用Console.ReadKey来阻止应用程序结束:

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...
}

这将使程序“永远”运行,直到您将exitProgram设置为true,此时它将正常退出。 “监视”不会被连续调用,因为resetEvent将无限期地阻止。当您的“工作”完成时(在FileSystemWatcher事件处理程序完成之后),请调用resetEvent.Set()。这将导致循环重复一次,重新触发您的监视代码。

它的工作原理是使用AutoResetEvent来阻止观察者重复“重新”重写相同的文件。

答案 1 :(得分:1)

应该更改Console应用程序的结构以使用WaitHandle和Ctrl + C退出程序。这种程序的基本结构如下所示。转换为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 :(得分:0)

this question读取,在这里,我认为您需要重构代码并从Winforms借用一个消息循环来保持您的程序活着。

添加对System.Windows.Forms.dll的引用。在您的主要方法中,启动您的观察者。然后调用Application.Run()请不要担心,您的应用仍然可以使用控制台等,Run()只会启动一个消息循环并阻止您的程序继续到主方法的结尾。

然后重构上一个问题的代码,这样就不会再次调用Main()

每当您想停止申请时,请致电Application.Exit()