4

원격 서버/네트워크 경로에서 22 개의 폴더를 모니터링하는 Windows 2008 Server에 C# (.Net Framework 3.5) 기반 Windows 서비스 응용 프로그램이 있습니다. 때때로 지금은 로그에서 예외가 발생합니다.FileSystemWatcher 예외 - 네트워크 BIOS 명령 한계에 도달했습니다.

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이기 때문에 내가 MaxMpxCT 등 이미 this onethis one 등의 유래에 관련 질문을 살펴 보았다, MaxCmds에 대한 레지스트리 키가없는, 그러나 그들 중 누구도이 문제를 해결하지 못한 것 같습니다.

문제를 해결하는 데 도움이나 안내가 필요합니다.

EDIT : Windows 2008 서버에서 MaxCMDs 한도를 높이는 방법에 대해서도 비슷한 question on ServerFaults을 추가했습니다.

EDIT 2 : 내 서버 호스팅 Windows 서비스에서 MaxCmds 및 MaxMpxCt 키를 만들고 해당 값을 250으로 설정했지만 아무런 효과가 없습니다. 나는이 기사를 따라 갔다. http://alitarhini.wordpress.com/2011/04/06/299/

+0

FileSystemWatcher는 * 값 비싼 * 운영 체제 리소스입니다. 파일 시스템은 이러한 알림을 생성하기 위해 많은 작업을해야합니다. 귀하의 운영 체제가 합리적인 것으로 간주하는 것의 당신의 우물. 물론 비합리적인 제한을 조정하여 문제를 해결하지는 마십시오. 더 적은 수의 관찰자를 사용하여 해결할 수 있습니다. –

+0

@HansPassant, 코멘트 주셔서 감사합니다. 필자는 22 개의 폴더를 모니터링해야하고, 앞으로는 증가 할 것입니다.'FileSystemWatcher'를 함께 모으고 여러 스레드에서 모든 디렉토리를 주기적으로 모니터하는 타이머를 사용하려고합니다. 이 방법이 자원을 덜 차지할 것이라고 생각하십니까? – user2711965

+0

불필요한 네트워크 트래픽과 다른 리소스를 많이 생성합니다. 타이머 간격을 10 분 정도의 적당한 값으로 설정하는 한 실제 문제는 아닙니다. –

답변

3

것들의 결정에 고려 "당신은 FSW 도랑해야하고 자신의 (RYO)를 롤?"합니다 :

  • 현재 22 개 폴더를 모니터링 할 수 있습니다. 이 번호는 올라갈 것입니까? 얼마나 높은?
  • 각 폴더에 몇 개의 파일이 있습니까? 몇? 몇 천 명?
  • 솔루션의 특성은 무엇입니까? 이 솔루션은 드롭 폴더 솔루션입니까? 즉, 다른 곳으로 파일을 즉시 옮길 수 있습니까? 또는 백업 유형의 솔루션, 여기서 파일을 서로 비교할 수 있습니까? 이들 각각은 원격 파일과 상호 작용하는 방법에 영향을 미칩니다.
  • 추가 FSW 이벤트를 생성하는 원격 파일 작업을 수행하고 있습니까? FSW 이벤트는 이름 바꾸기, 편집, 속성 변경, 플래그 및 권한 부여와 같은 많은 작업에 대해 발생합니다.
  • 초당 처리 할 수있는 모니터링 된 파일 작업 수는 몇 개입니까? 몇? 아니면 몇 천이나되는거야?
  • FSW는 네트워크 스택에서 최적화 된 호출을 사용하여 모니터링 대상 OS에서 이벤트를 발생시킵니다 (대상 OS가 Windows 98 인 경우). 전체 파일 목록을 가져와야하는 롤업 아래로 이동 한 다음 변경 사항에 대해 diff를 수행하십시오. FSW는 많은 파일이있는 곳에서 승리합니다. RYO 경우에만 승리가있을 수 있습니다. 모니터링되는 파일 시스템이 Windows 시스템이 아닌 경우 FSW는 RYO 솔루션과 동일한 방식으로 파일을 폴링합니다.
  • FSW는 높은 처리량으로 과부하가 걸릴 수 있습니다. 단일 작업으로 많은 사건이 FSW에 제기 될 수 있음을 인식하십시오. 노이즈를 필터링하기 위해 파일 유형 및 이벤트 유형 필터를 설정했는지 확인하십시오.
  • FSW는 비 페이징 메모리를 사용합니다. 충분한 RAM이 없어도 사용량이 많은 서버에서 처리량이 비싸고 장애가 발생할 수 있습니다. 22 개의 FSW 인스턴스가 신속하게 털이 얻을 수 있습니다.
  • 가능한 한 FSW 버퍼를 비워 두십시오! 이벤트를 처리하는 스레드에서 스레드를 FSW와 분리하여 FSW가 발생시키는 이벤트를 즉시 처리하고 버퍼에서 지울 것을 고려하십시오. 동시에 활성화 된 파일 수가 수십 가지라면 * Changed 이벤트에서 새 작업을 시작할 수 있습니다. 동시 활성 파일의 수가 수천 개에 달하면 작업을 수행하기 위해 제작자/고객 패턴을 구현해야합니다.
+0

당신의 대답에 +1, 내 특별한 문제에 대한 직접적인 대답은 없다는 것을 알고 있습니다. 감사합니다. – user2711965

1

당신이 그 열쇠가없는 경우 Windows 레지스트리에, 당신은 \ CurrentControlSet \ Services에 0 65535

HKEY_LOCAL_MACHINE을 \ 시스템 사이의 값을 DWORD로 만들 수 있습니다 \에 lanmanserver \는

매개 변수
+0

어디에서 그 열쇠를 만들어야합니까? 파일 서버 또는 Windows 서비스를 호스팅하는 서버에 있습니까? – user2711965

+0

오류가 발생하는 컴퓨터에서 추측됩니다. –

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