Pergunta

Acabamos de começar a nos deparar com um problema estranho com um FileSystemWatcher onde a chamada para Dispose() parece estar suspensa.Este é um código que funciona sem problemas há algum tempo, mas acabamos de atualizar para o .NET3.5 SP1, então estou tentando descobrir se mais alguém viu esse comportamento.Aqui está o código que cria o FileSystemWatcher:

if (this.fileWatcher == null)
{
   this.fileWatcher = new FileSystemWatcher();
}
this.fileWatcher.BeginInit();
this.fileWatcher.IncludeSubdirectories = true;
this.fileWatcher.Path = project.Directory;
this.fileWatcher.EnableRaisingEvents = true;
this.fileWatcher.NotifyFilter = NotifyFilters.Attributes;
this.fileWatcher.Changed += delegate(object s, FileSystemEventArgs args)
{
   FileWatcherFileChanged(args);
};
this.fileWatcher.EndInit();

A forma como isso está sendo usado é para atualizar a imagem de estado de um objeto TreeNode (ligeiramente ajustado para remover informações específicas do negócio):

private void FileWatcherFileChanged(FileSystemEventArgs args)
{
   if (this.TreeView != null)
   {
      if (this.TreeView.InvokeRequired)
      {
         FileWatcherFileChangedCallback d = new FileWatcherFileChangedCallback(FileWatcherFileChanged);
         this.TreeView.Invoke(d, new object[]
      {
         args
      });
      }
      else
      {
         switch (args.ChangeType)
         {
            case WatcherChangeTypes.Changed:
               if (String.CompareOrdinal(this.project.FullName, args.FullPath) == 0)
               {
                  this.StateImageKey = GetStateImageKey();
               }
               else
               {
                  projectItemTreeNode.StateImageKey = GetStateImageKey();
               }
               break;
         }
      }
   }
}

Está faltando alguma coisa ou isso é uma anomalia do .NET3.5 SP1?

Foi útil?

Solução

Apenas um pensamento...Alguma chance de haver um problema de impasse aqui?

Você está chamando TreeView.Invoke, que é uma chamada de bloqueio.Se uma alteração no sistema de arquivos ocorrer exatamente quando você clicar em qualquer botão que causa a chamada FileSystemWatcher.Dispose(), seu método FileWatcherFileChanged será chamado em um thread em segundo plano e chamará TreeView.Invoke, que será bloqueado até que seu thread de formulário possa processar a solicitação Invoke .No entanto, seu thread de formulário chamaria FileSystemWatcher.Dispose(), que provavelmente não retornará até que todas as solicitações de alteração pendentes sejam processadas.

Tente alterar .Invoke para .BeginInvoke e veja se isso ajuda.Isso pode ajudar a apontar a direção certa.

Claro, também pode ser um problema do .NET 3.5SP1.Estou apenas especulando aqui com base no código que você forneceu.

Outras dicas

Scott, ocasionalmente vimos problemas com control.Invoke no .NET 2.Tente mudar para control.BeginInvoke e veja se isso ajuda.

Isso permitirá que o thread FileSystemWatcher retorne imediatamente.Suspeito que seu problema seja de alguma forma que o control.Invoke esteja bloqueando, fazendo com que o FileSystemWatcher congele ao ser descartado.

Também estamos tendo esse problema.Nosso aplicativo roda em .Net 2.0, mas é compilado pelo VS 2008 SP1.Também tenho o .NET 3.5 SP1 instalado.Também não tenho ideia de por que isso acontece, não parece um problema de impasse da nossa parte, pois nenhum outro thread está em execução neste momento (é durante o desligamento do aplicativo).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top