FileSystemWatcher异常 - 已达到网络BIOS命令限制

时间:2014-05-22 15:38:10

标签: c# .net windows-services windows-server-2008 filesystemwatcher

我在Windows 2008 Server上有一个基于C#(。Net framework 3.5)的Windows服务应用程序,它监视远程服务器/网络路径上的22个文件夹。我不时会在日志中得到一个例外

  

System.ComponentModel.Win32Exception:已达到网络BIOS命令限制。

我尝试将InternalBufferSize增加到MAX(64K),但它对异常没有任何影响。

我已将其定义为:

在班级:

FileSystemWatcher fsw;

初始化方法

fsw = new FileSystemWatcher("FolderUNC");
fsw.IncludeSubdirectories = false;
//m_fsw.InternalBufferSize = 65536; -- Commented out to default 8K
fsw.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.Size;
fsw.Renamed += new RenamedEventHandler(OnChanged);
fsw.Deleted += new FileSystemEventHandler(OnChanged);
fsw.Changed += new FileSystemEventHandler(OnChanged);
fsw.Created += new FileSystemEventHandler(OnChanged);
fsw.Error += new ErrorEventHandler(OnFileSystemWatcherError);
fsw.EnableRaisingEvents = true;   

我还要确保将FileSystemWatcher对象置于Error或停止服务。喜欢

if (fsw != null)
    fsw.Dispose();

我已尝试关注article KB-810886,但由于我的服务器是Windows Server 2008,因此我没有MaxCmdsMaxMpxCT等的注册表项。我已经查看了关于Stackoverflow的相关问题,如this onethis one,但它们似乎都没有解决问题。

对于解决问题的任何帮助或指导表示赞赏。

编辑:我还添加了一个类似的question on ServerFaults,关于如何在Windows 2008服务器上提高MaxCMDs的限制。

编辑2:我已在我的服务器托管Windows服务上为MaxCmds和MaxMpxCt创建密钥,并将其值设置为250,但它没有任何效果。我跟着这篇文章。 http://alitarhini.wordpress.com/2011/04/06/299/

3 个答案:

答案 0 :(得分:3)

在你决定放弃FSW并推出自己的(RYO)时需要考虑的事项?":

  • 您目前正在监控22个文件夹。这个数字会上升吗?有多高?
  • 每个文件夹中有多少个文件?一些?还是几千?
  • 解决方案的性质是什么?这是一个drop-folder解决方案,您可以立即将文件移动到其他位置吗?或者是备份类型的解决方案,您在哪里将文件分散到位?其中每一项都会影响您与远程文件的交互方式。
  • 您是否正在执行可能会产生其他FSW事件的远程文件操作? FSW事件是通过重命名,编辑,更改属性,标志和权限等许多内容引发的。
  • 您需要每秒处理多少个受监控的文件操作?一些?还是几千?
  • FSW在网络堆栈中使用优化的调用,这些调用将从受监控的操作系统引发事件(假设目标操作系统是> Windows 98),而不是自己动手,你需要提取整个列表文件向下,然后将其差异化以进行更改。 FSW在有大量文件的地方获胜;如果只有少数,RYO 可能获胜。如果您的受监视文件系统不是Windows计算机,则FSW只会以与RYO解决方案相同的方式轮询文件。
  • FSW可能因高吞吐量而过载。意识到单个操作可以向FSW引发许多事件。确保您已设置文件类型和事件类型的过滤器以过滤掉噪音。
  • FSW使用非分页内存。它可能很昂贵,甚至在没有足够RAM的繁忙服务器上也会降低吞吐量。 22 FSW实例可以快速变得毛茸茸。
  • 尽可能保持FSW缓冲区为空! 考虑将线程与处理事件的线程中的FSW隔离,以便立即处理并从缓冲区中清除FSW引发的事件。如果并发活动的数量文件是几十个,你可以简单地在* Changed事件中启动一个新任务;如果并发活动文件的数量是数千个,那么您将要实现生产者/消费者模式来完成工作。

答案 1 :(得分:1)

如果您没有这些密钥,则可以在Windows注册表中将其创建为DWORD,其值介于0到65535之间。

HKEY_LOCAL_MACHINE \ SYSTEM \ CURRENTCONTROLSET \服务\ lanmanserver \参数

答案 2 :(得分:1)

这是一个示例文件系统轮询器。我对你的场景中的表现感兴趣。

void Main()
{
    var watcher = new DirectoryWatcher("C:\\test\\", new TimeSpan(0, 0, 1));
    watcher.Notification += (sender, args) => 
        Console.WriteLine(string.Format("{0} was {1}", args.FileName, args.NotificationType));

    watcher.Start();

    Console.WriteLine("Press enter to stop.");
    Console.ReadLine();

    watcher.Stop();
}

public class DirectoryWatcher
{
    public DirectoryWatcher(string directory, TimeSpan pollingFrequency)
    {
        this.Directory = directory;
        this.PollingFrequency = pollingFrequency;
    }

    public string Directory { get; set; }
    public TimeSpan PollingFrequency { get; set; }

    public System.Threading.Timer Timer { get; set; }

    private long ProcessCount;

    public void Start()
    {
        this.Timer = new Timer(Tick, null, 0, (int)PollingFrequency.TotalMilliseconds);
    }

    public void Stop()
    {
        this.Timer.Dispose();
    }

    DirectoryState previousState;

    private void Tick(object stateInfo)
    {
        if(Interlocked.Increment(ref ProcessCount) == 1)
        {
            try
            {
                if(previousState == null)
                {
                    // First Run.
                    // Tell listeners about files that already exist in the directory.
                    previousState = new DirectoryState(this.Directory);

                    foreach(var file in previousState.Files)
                    {
                        RaiseNotification(file.Key, DirectoryWatcherNotifiction.StartUp);
                    }
                }
                else
                {
                    var currentState = new DirectoryState(this.Directory);
                    NotifyChanges(previousState, currentState);
                    previousState = currentState;
                }
            }
            catch(Exception ex)
            {
                if(this.Error != null)
                {
                    this.Error(this, new ErrorEventArgs(ex));
                }
            }
        }
        Interlocked.Decrement(ref ProcessCount);
    }

    private void NotifyChanges(DirectoryState previous, DirectoryState current)
    {
        // Notify changes and deletions.
        foreach(string fileName in previous.Files.Keys)
        {
            if(current.Files.ContainsKey(fileName))
            {
                if(!current.Files[fileName].Equals(previous.Files[fileName]))
                {
                    RaiseNotification(fileName, DirectoryWatcherNotifiction.Changed);
                }
            }
            else
            {
                RaiseNotification(fileName, DirectoryWatcherNotifiction.Deleted);
            }
        }

        // Notify new files.
        foreach(string fileName in current.Files.Keys)
        {
            if(!previous.Files.ContainsKey(fileName))
            {
                RaiseNotification(fileName, DirectoryWatcherNotifiction.Created);
            }
        }
    }

    private void RaiseNotification(string fileName, DirectoryWatcherNotifiction notificationType)
    {
        if(this.Notification != null)
        {
            this.Notification(this, new DirectoryWatcherEventArgs(fileName, notificationType));
        }
    }

    public EventHandler<DirectoryWatcherEventArgs> Notification { get; set; }
    public EventHandler<ErrorEventArgs> Error { get; set; }
}

public class DirectoryWatcherEventArgs
{
    public DirectoryWatcherEventArgs(string fileName, DirectoryWatcherNotifiction notificationType)
    {
        this.FileName = fileName;
        this.NotificationType = notificationType;
    }

    public string FileName { get; set; }
    public DirectoryWatcherNotifiction NotificationType { get; set; }
}

public enum DirectoryWatcherNotifiction
{
    StartUp,
    Deleted,
    Changed,
    Created
}

public class DirectoryState
{
    private DirectoryState()
    {
        this.Files = new Dictionary<string, DirectoryFileInfo>();
    }

    public DirectoryState(string directory) 
        : this()
    {
        this.DirectoryName = directory;

        foreach(var file in Directory.EnumerateFiles(directory))
        {
            this.Files.Add(file, new DirectoryFileInfo(file));
        }
    }

    public string DirectoryName { get; set; }
    public Dictionary<string, DirectoryFileInfo> Files { get; set; }
}

public class DirectoryFileInfo
{
    public DirectoryFileInfo(string fileName)
    {   
        var info = new FileInfo(fileName);
        this.LastWriteTime = info.LastWriteTime;
        this.FileSize = info.Length;
    }

    public DateTime LastWriteTime { get; set; }
    public long FileSize { get; set; }

    public bool Equals(DirectoryFileInfo other)
    {
        return this.LastWriteTime == other.LastWriteTime && this.FileSize == other.FileSize;
    }
}