すでに述べたように、Mono には「System.IO.FileSystemWatcher」というクラスがあります。これは関連リンクです:http://www.go-mono.com/docs/monodoc.ashx?link=T%3aSystem.IO。 FileSystemWatcher
<ブロック引用>「Mono の FileSystemWatcher の実装には複数のバックエンドがあります。Mono がサポートするすべてのオペレーティング システムが、アプリケーションが期待する機能を提供するために必要なすべての機能を備えているわけではないため、これが必要です。
オペレーティング システム カーネルがディレクトリの監視をサポートしている場合 (Linux では inotify、BSD または OSX では KEvents)、その機能が使用されます。それ以外の場合は、Gamin または FAM ライブラリ (これらのライブラリはディレクトリを監視するための API を提供します) を使用するようにフォールバックし、これらの機能が使用できない場合、Mono はディレクトリを監視する 750 ミリ秒ごとにポーリングします。
アプリケーションを実行する前に MONO_MANAGED_WATCHER 環境変数を設定することにより、(カーネル サポートを使用する代わりに) ポーリング動作を強制することができます。これは、inotify をサポートせず、変更を検出するためにポーリングが必要なファイルシステムに役立つ可能性があります。"
それは、ファイル改ざんモニターまたは Inotify の Gamin です。
編集:Mono には Gamin バインディングがあります。実際、その FileSystemWatcher の実装は Gamin を使用しています。 https://www.mono-project.com/docs/faq/technical/#what-are-the-issues-with-filesystemwatcher.
<ブロック引用>FileSystemWatcher にはどのような問題がありますか?
FileSystemWatcher の Mono 実装には多数のバックエンドがあり、最も最適なバックエンドがあり、依存関係が少ないのは inotify-backend (Mono 1.1.17 以降のバージョンで利用可能) です。
このバックエンドを使用すると、カーネルはファイル システム上のファイルへの変更に関する更新を Mono に提供しますが、inotify 対応のカーネルが必要であり、新しい Linux ディストリビューションのみが出荷されます。
古い Linux システムでは、FAM または Gamin をインストールしておく必要があります (どちらでも動作します)。 -devel パケットのインストールが必要になる場合があります。
*BSD ファミリーには、実行時に検出されたときに使用される Kqueue ベースの実装があります。
上記のいずれも機能しない場合、Mono はフォールバックしてディレクトリの変更をポーリングしますが、これは最適とは言えません。
Ubuntu 10.10 の Mono で FileSystemWatcher を使用して観察したことを共有したいと思います。これは C# での FileSystemWatcher の非常に単純な実装です
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.IO;
using System.Reflection;
namespace FileSystemWatcherSandbox
{
public class Program
{
static void Main(string[] args)
{
foreach(DictionaryEntry de in Environment.GetEnvironmentVariables())
{
Console.WriteLine("{0} = {1}",de.Key,de.Value);
}
string basePath = AppDomain.CurrentDomain.BaseDirectory;
Console.WriteLine("watching: {0}", basePath);
FileSystemWatcher fsw = new FileSystemWatcher(basePath);
fsw.Changed += new FileSystemEventHandler(fsw_Changed);
fsw.Created += new FileSystemEventHandler(fsw_Created);
fsw.Deleted += new FileSystemEventHandler(fsw_Deleted);
fsw.Error += new ErrorEventHandler(fsw_Error);
fsw.Renamed += new RenamedEventHandler(fsw_Renamed);
fsw.EnableRaisingEvents = true;
fsw.IncludeSubdirectories = true;
while (true)
{
WaitForChangedResult result = fsw.WaitForChanged(WatcherChangeTypes.All,10000);
Console.WriteLine(result.TimedOut ? "Time out" : "hmmm");
}
}
static void fsw_Renamed(object sender, RenamedEventArgs e)
{
Console.WriteLine("({0}): {1} | {2}", MethodInfo.GetCurrentMethod().Name, e.ChangeType, e.FullPath);
}
static void fsw_Error(object sender, ErrorEventArgs e)
{
Console.WriteLine("({0}): {1}", MethodInfo.GetCurrentMethod().Name, e.GetException().Message);
}
static void fsw_Deleted(object sender, FileSystemEventArgs e)
{
Console.WriteLine("({0}): {1} | {2}", MethodInfo.GetCurrentMethod().Name, e.ChangeType, e.FullPath);
}
static void fsw_Created(object sender, FileSystemEventArgs e)
{
Console.WriteLine("({0}): {1} | {2}", MethodInfo.GetCurrentMethod().Name, e.ChangeType, e.FullPath);
}
static void fsw_Changed(object sender, FileSystemEventArgs e)
{
Console.WriteLine("({0}): {1} | {2}", MethodInfo.GetCurrentMethod().Name, e.ChangeType, e.FullPath);
}
}
}
このコードはテスト済みで、Windows XP と Ubuntu 10.10 の両方で動作します。ただし、Ubuntu 10.10 (おそらく以前のバージョンも) では、FileSystemWatcher が独自の動作をすることを指摘しておきます。
監視対象のディレクトリにサブディレクトリが含まれていない場合、IncludeSubdirectories プロパティを true に設定して FileSystemWatcher を呼び出すと、FileSystemWatcher はイベントを無視します。ただし、ターゲット ディレクトリにサブディレクトリがある場合は、IncludeSubdirectories を true に設定すると期待どおりに機能します。
常に機能するのは、IncludeSubdirectories が false に設定されている場合です。この場合、FileSystemWatcher はターゲット ディレクトリのみを監視します。
これが、さまざまなオペレーティング システムで Mono を利用し、FileSystemWatcher タイプを呼び出したいプログラマーにとって役立つことを願っています。