2014-01-06 66 views
2

我有以下代码用于监视文本文件的目录,目录每天获取两次新文件,代码可以在某段时间内正常工作,但在此之后它会停止触发OnCreated事件。 。FileSystemWatcher在某段时间不会触发

[PermissionSet(SecurityAction.Demand, Name="FullTrust")] 
public static void Run() 
{ 
    FileSystemWatcher watcher = new FileSystemWatcher(); 
    watcher.Path = @"c:\users\documents\"; 

    watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite 
     | NotifyFilters.FileName | NotifyFilters.DirectoryName; 

    watcher.Filter = "*.txt"; 

    // Add event handlers. 
    watcher.Created += new FileSystemEventHandler(OnCreated); 

    // Begin watching. 
    watcher.EnableRaisingEvents = true; 

    // Wait for the user to quit the program. 
    Console.WriteLine("Press \'q\' to quit the sample."); 
    while(Console.Read()!='q'); 
} 

private static void OnCreated(object source, FileSystemEventArgs e) 
{ 
    Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType); 
} 

想不通的问题。

另外,我想知道这种万无一失的选择(如果有的话),因为我没有找到这个可靠..

+0

需要注意的是'FileSystemWatcher'有一点一个不可靠的声誉(尽管我不确定这是否是FileSystemWatcher实现的问题或者它是如何被使用的)。请参阅http://stackoverflow.com/questions/239988/filesystemwatcher-vs-polling-to-watch-for-file-changes以获得有关其他人如何处理该问题的建议。 –

+0

另外,我的理解是'FileSystemWatcher'使用系统的'ReadDirectoryChangesW' API。 Jim Beveridge在该API的详细信息中阅读本文可能会有帮助:http://qualapps.blogspot.com/2010/05/understanding-readdirectorychangesw.html –

回答

4

这样做的问题是,对FileSystemWatcher的基准正由GC收集和一段时间后因此FILEWATCHER有空引用导致事件没有得到提升。

解决方案: -

private static FileSystemWatcher watcher; 
public static void Run() 
{ 
watcher = new FileSystemWatcher(); 
... 
GC.KeepAlive(watcher); 
} 

只是保持在外部范围观察者的参考的建议并没有解决问题。我曾明确指出GC不应该收集FileWatcher对象。

7

因为Run方法完成后,watcher是符合垃圾回收。 这意味着经过一段时间watcher将被收集,显然将停止举办活动。

为了解决,保持在所述外范围观察者的参考:

private static FileSystemWatcher watcher; 

public static void Run() 
{ 
    watcher = new FileSystemWatcher(); 
    ... 
} 
+0

不确定提供的原因是否正确。 Run方法不会退出,直到有人按下字母'q',并且局部变量仍然有效且不符合GC条件。我错了吗? – Steve

+3

@Steve:引用的生命周期不一定由变量的范围扩展,只能由引用是否为“活动”来扩展。由于'watcher.EnableRaisingEvents = true'后'watcher'局部变量不再使用,GC可能会认为它不活动并可能收集它。 –

+0

@MichaelBurr你可以给我一些参考(没有双关语意图),因为,正如我所看到的,本地变量观察者(直到退出Run方法)仍然引用堆中有效的对象,GC不应该破坏当对象仍然存在对活动对象的引用时的对象。 – Steve

0

假设你的守望者是不是走出去的范围,还有你可以检查发生的诸如跑出观察家内部缓冲区中的任何错误... watcher.Error += Watcher_Error; ... private void Watcher_Error(object sender, ErrorEventArgs e) { Debug.WriteLine("Watcher_Error: " + e.GetException().Message); }

相关问题