问题描述:

I have a dnx console application on a Ubuntu VM that watches a folder which is shared with the host OS (Windows 8.1). When file changes occurs in the shared folder on the Ubuntu VM, the console application responds to them but not when file changes are made on the host. How come and is there anyway to make it work?

using System;

using System.IO;

public class Program

{

public static void Main(string[] args)

{

FileSystemWatcher watcher = new FileSystemWatcher();

watcher.Path = "/media/sf_shared";

watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;

watcher.Changed += new FileSystemEventHandler(Respond);

watcher.Created += new FileSystemEventHandler(Respond);

watcher.Deleted += new FileSystemEventHandler(Respond);

watcher.EnableRaisingEvents = true;

Console.ReadKey();

}

private static void Respond(object source, FileSystemEventArgs e)

{

Console.WriteLine("Hej");

}

}

网友答案:

On Linux, Mono will use inotify as its preferred event publishing backend to the the FileSystemWatcher class. The issue in your case is that a change to the filesystem by Windows is not going to cause the Ubuntu/Linux filesystem to publish an event... Windows to Windows UNC sharing paths do publish file system events, but cross-platform file system sharing 'typically' do not.. i.e. embedded Samba in a VM host... not a hard rule, but each deployed environment needs tested.

The only way for this to happen in your case is a polling system, which mono does support, if fact it supports 5 different backends for file system eventing out of the box.

You can force it to use the built-in polling method (do this before the file watch object creation):

Environment.SetEnvironmentVariable ("MONO_MANAGED_WATCHER", "1");

Or set the environment var before running the app:

export MONO_MANAGED_WATCHER=1

Buyer beware: It is a performance issue when polling. This will cause a dir scan on what you defined in your watcher ever 750ms. Keep your watcher to one dir, no sub dirs, and preferable that it is filtered to a very small file subset (one?) and if possible only have one file in that dir....

This was documented at one time in the mono docs, but I can not longer find it there (but it is in the source code ;-) :

https://github.com/mono/mono/blob/88d2b9da2a87b4e5c82abaea4e5110188d49601d/mcs/class/System/System.IO/FileSystemWatcher.cs#L115

Online Doc: http://docs.go-mono.com/monodoc.ashx?link=T%3aSystem.IO.FileSystemWatcher

Old doc notes (might be in the man page for mono?):

"Mono's implementation of the FileSystemWatcher has multiple backends. This is necessary because not all operating systems supported by Mono have all the features necessary to provide the functionality expected by applications.

If the operating system kernel supports watching directories (inotify on Linux, KEvents on BSD or OSX) that feature is used; Otherwise it falls back to using the Gamin or FAM libraries (these libraries provide an API to monitor directories) and if none of those features are available, Mono will poll every 750 milliseconds the directories watched.

You can force the polling behavior (instead of using the kernel support) by setting the MONO_MANAGED_WATCHER environment variable before executing your application. This might be useful for filesystems that do not support inotify and still require polling to detect changes."

相关阅读:
Top