简体   繁体   English

提要输入到Console.ReadKey

[英]Feed input to Console.ReadKey

I have a program that calls a Filewatcher function, like this 我有一个调用Filewatcher函数的程序,像这样

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. 我结尾处有console.readkey,因为在监视文件更改时,我不希望控制台显示“按任意键继续”。 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. 现在,如果检测到更改,则会触发另一个函数,该函数将执行其操作,并最终再次调用main,该函数再次在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. 我猜是这样,因为之前的console.readkey仍在等待输入,因此第一个输入转到那里,然后第二个输入转到第二个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? 所以,我的问题是,第一次触发文件监视程序时,我可以通过代码将某些内容提供给console.readkey,这就是在等待用户输入吗?

Console.ReadKey will block the program until you press a key (at which point it will read that and return). Console.ReadKey将阻止程序,直到您按下一个键为止(此时它将读取该内容并返回)。

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: 与其使用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...
}

This will make the program run "forever", until you set exitProgram to true, at which point it will exit normally. 这将使程序“永远”运行,直到将exitProgram设置为true为止,此时它将正常退出。 The "watch" will not get called continually, since resetEvent will block indefinitely. “ watch”将不会被连续调用,因为resetEvent将无限期阻塞。 When your "work" finishes (after the FileSystemWatcher event handler completes), call resetEvent.Set() . 当您的“工作”完成时(在FileSystemWatcher事件处理程序完成之后),请调用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. 它通过使用AutoResetEvent起作用,以防止观察者重复“重新监视”同一文件。

The structure of your Console application should be changed to use a WaitHandle and Ctrl+C to exit the program. 控制台应用程序的结构应更改为使用WaitHandle和Ctrl + C退出程序。 The basic structure of such a program is shown below. 这种程序的基本结构如下所示。 It should be trivial to convert to 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

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. 这个问题开始阅读,我认为您需要重构代码并从Winforms借用消息循环以使程序保持活动状态。

Add a reference to System.Windows.Forms.dll . 添加对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. 然后调用Application.Run()不用担心,您的应用程序仍然可以使用控制台,等等, Run()只会启动消息循环,并防止您的程序继续到main方法的末尾。

Then refactor your code from the previous question so it doesn't call Main() again. 然后从上一个问题重构您的代码,这样它就不会再次调用Main()了。

Whenever you want to stop your application, call Application.Exit() . 每当您要停止应用程序时,请调用Application.Exit()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM