我有一个调用Filewatcher函数的程序,比如这个
Main()
{
watch();
console.Readkey();
}
我最后有console.readkey,因为我不希望控制台在监视文件进行更改时显示“按任意键继续”。现在,如果检测到一个更改,另一个函数会被触发关闭,这会完成它的工作,并最终再次调用main,它再次在console.readkey处停止。
此时,我遇到了一些奇怪的问题,例如程序需要两个关键输入才能继续。我猜那是因为之前的console.readkey仍在等待输入,所以第一个输入进入那里,然后第二个输入进入第二个console.readkey。
所以,我的问题是,第一次触发filewatcher时,我可以通过代码向console.readkey提供一些内容,等待用户输入吗?
答案 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()
。