FileSystemWatcher Dispose コールがハングする
-
09-06-2019 - |
質問
Dispose() の呼び出しがハングしているように見えるという、FileSystemWatcher に関する奇妙な問題に遭遇し始めました。これはしばらく問題なく動作していたコードですが、.NET3.5 SP1 にアップグレードしたばかりなので、他の誰かがこの動作を確認したかどうかを調べています。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();
これは、TreeNode オブジェクトの状態イメージを更新するために使用されます (ビジネス固有の情報を削除するためにわずかに調整されています)。
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;
}
}
}
}
何か足りないものがあるのでしょうか、それとも .NET3.5 SP1 からの異常なのでしょうか?
解決
ちょっとした考え...ここでデッドロックの問題が発生する可能性はありますか?
TreeView.Invoke を呼び出していますが、これはブロック呼び出しです。FileSystemWatcher.Dispose() 呼び出しを引き起こすボタンをクリックしたときにファイルシステムの変更が発生した場合、FileWatcherFileChanged メソッドはバックグラウンド スレッドで呼び出され、TreeView.Invoke が呼び出されます。これは、フォーム スレッドが Invoke リクエストを処理できるようになるまでブロックされます。 。ただし、フォーム スレッドは FileSystemWatcher.Dispose() を呼び出しているため、保留中の変更要求がすべて処理されるまで関数は返されない可能性があります。
.Invoke を .BeginInvoke に変更して、それが役立つかどうかを確認してください。それはあなたを正しい方向に導くのに役立つかもしれません。
もちろん、.NET 3.5SP1 の問題である可能性もあります。ここでは、提供されたコードに基づいて推測しているだけです。
他のヒント
Scott、.NET 2 では control.Invoke に関する問題が時々発生しています。control.BeginInvoke に切り替えて、それが役立つかどうかを確認してください。
そうすることで、FileSystemWatcher スレッドがすぐに戻ることができるようになります。あなたの問題は、何らかの形で control.Invoke がブロックされているため、破棄時に FileSystemWatcher がフリーズするのではないかと思います。
私たちもこの問題を抱えています。私たちのアプリケーションは .Net 2.0 上で実行されますが、VS 2008 SP1 によってコンパイルされています。.NET 3.5 SP1 もインストールしています。なぜこれが起こるのか私にもわかりませんが、この時点では他のスレッドが実行されていないため(アプリケーションのシャットダウン中です)、こちら側でデッドロックの問題があるようには見えません。