如何让一个FileSystemWatcher线程永久运行?

7
我需要一个FileSystemWatcher在无限循环中运行,以监视文件的更改,但是这个文件只会每隔几天甚至一周才会更改。在MSDN FileSystemWatcher 的示例中,有一个循环,当用户没有在控制台输入q时:
while(Console.Read()!='q');

我不希望这个程序一直处于可用状态,以免被意外终止 - 它必须在无限循环中运行,无需用户干预。 我需要更改循环吗?
while (true);

所以线程不会退出?仅此一项并不理想,因为它会使CPU占用率飙升 - 添加Thread.Sleep调用将消除CPU负载,并且在这种情况下,可以长时间休眠,因为文件很少更改。这是最好的方法吗?我应该如何确保此线程保持活动状态,以便FileSystemWatcher在文件更改时起作用?这正在运行在一个Windows服务器上(使用.NET Framework版本2.0),因此如果必要,可以将其设置为Windows服务。

5个回答

10

如果这是在服务器上运行,服务似乎是一个很好的选择。

如果你想要更多交互性,我有一个小应用程序,它常驻工具栏并告诉我Issues文件夹中发生了什么事情。它使用Application.Run()方法来保持自身运行而不需要循环。

class MainEntryClass
{
    static void Main(string[] args)
    {
        FolderAlerter fa = new FolderAlerter(); 
        Application.Run();
    }
}

然后我在FolderAlerter中设置了我的FileSystemWatcher。


3
基本上,FileSystemWatcher是使用一些内建钩子来订阅更改,并请求操作系统在更改发生时调用您的委托。因此,您需要停止主线程退出,而不必实际执行任何操作;到达该行时,程序的主要部分已经结束,已经完成了所需的操作。
想要实现您想做的简单方法是对MSDN示例进行以下更改:
//while (Console.Read() != 'q') ;
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);

这将使您的主线程永久休眠,但仍允许委托触发并响应目录中的更改。请注意,它将在多个更改中保持运行(就像MSDN示例一样)。
请注意,MSDN示例中的“while”实际上并没有做太多事情;您可以将该行替换为“Console.Read()”,这样任何按键都会退出应用程序。它只是一行代码,以防止主线程在事件通知到达时退出。
然而,使用Sleep(Timeout.Infinite)会使您的应用程序处于无法轻松停止的状态,除非通过终止应用程序来停止。如果您将其编写为控制台应用程序,为什么不坚持“按Q键退出”?如果您决定将其编写为服务,则可能没问题,只要处理关机/重启等事件即可。

Application.Run()是更好的方法,因为它设置了所需的消息处理循环。我不确定,但我认为当用户尝试关闭Windows时,这种方法会触发“应用程序未响应”的消息。 - Jesse Weigert
它在我的测试中没有出现问题 - 但是我同意,这不是一个好的做法,因此我的“但是......” :) - flytzen

1

为此,您可能想要创建一个处于重置状态的ManualResetEvent,并让您的主线程WaitOne()等待它。要终止,一些其他回调可以简单地Set()事件,这将导致WaitOne()返回。


0

您可以使用Thread.Sleep来避免空循环。但是,例如系统重新启动时,Windows服务将自动重启。另一种方法是,根据程序/系统的架构方式,在单独的.exe文件中使用Windows计划任务程序运行轮询逻辑。

如果您正在寻找一个强大/有弹性的解决方案,Windows服务或基于Windows计划任务程序的方法似乎更可取。


0

Sysinternals(现在由Microsoft拥有)拥有FileMon,它将为您提供所需的内容和源代码。

引用该网站的话

FileMon的核心在于虚拟设备驱动程序Filevxd.vxd。它是动态加载的,在初始化时通过VxD服务IFSMGR_InstallFileSystemApiHook安装文件系统过滤器,以将自身插入到所有文件系统请求的调用链中。

二进制文件和源代码可以在此处找到:http://technet.microsoft.com/en-us/sysinternals/bb896642.aspx


源代码实际上是相当旧的版本。IFS Kit网站(http://www.microsoft.com/whdc/devtools/ifskit/default.mspx)提供了更新的源代码(其中一个示例与FileMon使用的相同,并且底层的ReadDirectoryChanges Win32调用也是如此)。 - Not Sure

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接