【问题标题】:FileSystemWatcher Exception - The network BIOS command limit has been reachedFileSystemWatcher 异常 - 已达到网络 BIOS 命令限制
【发布时间】:2014-07-11 18:12:39
【问题描述】:

我在 Windows 2008 Server 上有一个基于 C#(.Net 框架 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 对象。喜欢

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/

【问题讨论】:

  • FileSystemWatcher 是一种昂贵的操作系统资源。文件系统必须做很多工作才能生成这些通知。您的操作系统认为合理的南端。你当然不能通过调整不合理限制来解决这个问题,而是通过使用更少的观察者来解决它。
  • @HansPassant,感谢您的评论。我必须监视 22 个文件夹,并且将来可能会增加,我正在考虑将 FileSystemWatcher 全部丢弃,并使用计时器在多个线程中定期监视所有目录。您认为这种方法会减少资源消耗吗?
  • 您将产生更多不必要的网络流量,这是另一种资源。只要您将计时器的间隔设置为合理的值,例如 10 分钟,那么这不是真正的问题。
  • @HansPassant,再次感谢,这对我来说是不行。你能告诉我如何提高限​​制吗?我是否必须增加我的服务器托管 Windows 服务的限制?或在具有要监视的文件夹的文件服务器上。再次感谢。
  • @HansPassant -- 你或我无法判断他应该多久投票一次或应该投票多少次。每种情况都是不同的,简单地用“资源太密集”来打消他的问题是没有帮助或有用的。此外 - 监视 22 个文件夹至少不是资源密集型的。 user2711965 - 您是否可以使用带有缓存的 .NET 4.5 来使用 hostfilewatcher? msdn.microsoft.com/en-us/library/…

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


【解决方案1】:

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

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters

【讨论】:

  • 我应该在哪里创建这些密钥?在文件服务器上还是在托管 Windows 服务的服务器上?
【解决方案2】:

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

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;
    }
}

【讨论】:

    【解决方案3】:

    在决定“是否应该放弃 FSW 并推出自己的 (RYO)?”时需要考虑的事项:

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

    【讨论】:

    • +1 为您的回答,我知道我的特定问题没有直接的答案,谢谢。
    猜你喜欢
    • 2012-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    相关资源
    最近更新 更多