3

我有一个应用程序,它设置了 FileSystemWatcher。它应该无限期地运行。

让它在空闲循环中运行的最佳方法是什么?

我目前在做

FileSystemWatcher watch = ... //setup the watcher
watch.EnableRaisingEvents = true;
while (true) 
{
    Thread.Sleep(int.MaxValue);
}

这似乎有效(即,捕获事件并且不会在繁忙的循环中耗尽核心)。

还有什么成语吗?这种方法有什么问题吗?

4

5 回答 5

9

FileSystemWatcher.WaitForChanged 是阻塞的(同步的)。绝对不需要空闲循环,尤其是因为您正在处理事件。注意 EnableRaisingEvents 默认为 true。因此,您所要做的就是将组件添加到表单中。没有空闲循环。没有线程,因为组件负责处理。

我了解到您正在使用控制台应用程序。因此,您可以创建以下循环。同样,不需要空闲循环。该组件负责所有细节。

    Do
        Dim i As WaitForChangedResult = Me.FileSystemWatcher1.WaitForChanged(WatcherChangeTypes.All, 1000)
    Loop Until fCancel

[更新]“注意 EnableRaisingEvents 默认为 true。” 根据 Microsoft 源代码,只有将 FileSystemWatcher 组件放到设计器上时才适用。如下所示:

    /// <internalonly/>
    /// <devdoc>
    /// </devdoc>
    [Browsable(false)] 
    public override ISite Site {
        get { 
            return base.Site; 
        }
        set { 
            base.Site = value;

            // set EnableRaisingEvents to true at design time so the user
            // doesn't have to manually. We can't do this in 
            // the constructor because in code it should
            // default to false. 
            if (Site != null && Site.DesignMode) 
                EnableRaisingEvents = true;
        } 
    }

[更新] 在语句WaitForChanged之前和之后调用设置 EnableRaisingEvents。System.Threading.Monitor.Wait

于 2009-09-14T10:12:43.330 回答
5

正如我从您的评论中了解到的那样,您需要您的应用程序无限期地运行,它是一个控制台应用程序,由另一个可执行文件提供午餐。

最好使用 Console.ReadLine 而不是循环。或使用 Monitor.Wait 方法无限期阻塞线程

object sync = new object();
lock(sync)
Monitor.Wait(sync);
于 2009-09-14T10:11:34.863 回答
2

Thread.Sleep() 会做你想做的事。但基本上你应该阻止使用一种操作系统方法来唤醒你想要的策略。例如。Console.ReadLine() 或在事件处理程序命中的互斥体上消失。

您不必杀死您的应用程序以使其关闭。

如果您将代码嵌入到表单中,那么至少可以很好地终止该表单,并且在您不使用它时具有合理的操作系统负载。

于 2009-09-14T09:54:48.287 回答
2

如果您将此循环运行的线程标记为后台线程(Thread.IsBackground 属性),那么它应该可以正常工作(当所有非后台线程终止时程序将退出)

于 2009-09-14T09:58:43.380 回答
0

我不明白...你为什么要和空闲循环?你想让你的应用程序无限期地运行吗?

那么,为什么不创建一个 Windows 服务,或者一个可以在系统托盘中运行的应用程序呢?

然后,我要做的是创建一个只执行此操作的类:

public class Foo
{
   private FileSystemWatcher _fs;

   private volatile bool _stopped = false;

   public Foo()
   {
       _fs = new FileSystemWatcher();
       ...
   }

   public void Start()
   {
       _stopped = false;
       Thread t = new Thread (new ThreadStart(DoWork));
       t.Start();
   }

   private void DoWork()
   {
       while( !_stopped )
       {
           Thread.Sleep(1);
       }
   }

   public void Stop()
   {
       _stopped = true;
   }

}
于 2009-09-14T09:55:43.463 回答