У меня есть следующий код, который регистрирует FileSystemWatcher
а затем запускает какой-то метод DoRequiedWork()
Всякий раз, когда происходит событие записи в указанном файле. Существует также некоторая логика, чтобы предотвратить запуск нескольких событий при каждой записи (с lastRead
а также lastWriteTime
):
// To prevent multiple events from firing
static DateTime lastRead = DateTime.MinValue;
static string UserName = GetUserName();
private static void Run()
{
// Create a new FileSystemWatcher and set its properties.
var watcher = new FileSystemWatcher
{
Path = $@"\\file\home$\{UserName}\Application Data",
NotifyFilter =
NotifyFilters.LastWrite,
Filter = "filetowatch.txt"};
// Activate
watcher.Changed += OnChanged;
watcher.EnableRaisingEvents = true;
while (true)
{
System.Threading.Thread.Sleep(10000);
}
}
private static void OnChanged(object source, FileSystemEventArgs e)
{
var lastWriteTime = File.GetLastWriteTime(e.FullPath);
if (lastWriteTime == lastRead) return;
DoRequiredWork();
lastRead = lastWriteTime;
}
Я хотел бы реализовать это с помощью c++
апи ReadDirectoryChangesW
в попытке улучшить производительность, но я не уверен, как это сделать.
Я проверил PInvoke, и можно увидеть, что подпись может быть определена как:
[DllImport("kernel32.dll")]
static extern bool ReadDirectoryChangesW(IntPtr hDirectory, IntPtr lpBuffer,
uint nBufferLength, bool bWatchSubtree, uint dwNotifyFilter, out uint
lpBytesReturned, IntPtr lpOverlapped,
ReadDirectoryChangesDelegate lpCompletionRoutine);
Я хотел бы начать с того, как создать это, но сначала хотел проверить, действительно ли это будет работать лучше, чем стандартный управляемый c # FileSystemWatcher
,
В качестве альтернативы (или в дополнение к) я хотел бы знать, существует ли лучший способ сохранить приложение работающим в фоновом режиме (без пользовательского интерфейса), чем:
while (true)
{
System.Threading.Thread.Sleep(10000);
}
Как мне кажется, это не лучший способ держать приложение открытым, но я не уверен.
Кто-нибудь может посоветовать?
Похоже, что вы держитесь за поток в вашем методе Run. Не делай этого. Вместо этого держите статическую ссылку вокруг. Похоже, вы смотрите сетевую долю. Не ожидайте высокой производительности, так как это касается не только дисковой подсистемы, но и сетевой подсистемы (на вашей стороне и на сервере). Существует слишком много факторов, чтобы ожидать, что использование одного и того же API-интерфейса внезапно приведет к огромному увеличению производительности.
static FileSystemWatcher watcher;
private static void Run()
{
// Create a new FileSystemWatcher and set its properties.
// if you're watching a network share, don't expect huge performance
// as the network is involved
watcher = new FileSystemWatcher
{
Path = $@"\\file\home$\{UserName}\Application Data",
NotifyFilter =
NotifyFilters.LastWrite,
Filter = "filetowatch.txt"};
// Activate
watcher.Changed += OnChanged;
watcher.EnableRaisingEvents = true;
AppDomain.CurrentDomain.DomainUnload += (s,e) => {
var w = watcher as IDisposable;
if (w != null) w.Dispose();
};
}
Других решений пока нет …