I am trying to create a windows service to watch the file changes in a specific directory. I am using dotnet core 6 and a BackgroundService.
I created a separate class named FileMonitor in which I simply paste the Microsoft FileSystemWatcher example
public void MyWatcher(string folder)
{
using var watcher = new FileSystemWatcher(folder);
watcher.NotifyFilter = NotifyFilters.Attributes
| NotifyFilters.CreationTime
| NotifyFilters.DirectoryName
| NotifyFilters.FileName;
watcher.Changed += OnChanged;
watcher.Created += OnCreated;
watcher.Filter = "*.txt";
watcher.EnableRaisingEvents = true;
}
private void OnChanged(object sender, FileSystemEventArgs e)
{
if (e.ChangeType != WatcherChangeTypes.Changed)
{
return;
}
Console.WriteLine($"Changed: {e.FullPath}");
}
private void OnCreated(object sender, FileSystemEventArgs e)
{
string value = $"Created: {e.FullPath}";
Console.WriteLine(value);
}
And in my BackgroundService I am creating an instance of FileMonitor and calling the method MyWatcher as below.
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
FileMonitor fm = new FileMonitor();
fm.MyWatcher($"C:\test");
while (!stoppingToken.IsCancellationRequested)
{
}
}
I am not getting any console logs about the file change
>Solution :
using var watcher = new FileSystemWatcher(folder);
That using right there will dispose of the watcher at the end of that function, so as soon as it sets up the events. They will never get called.
You need to keep the objects alive and rooted for their entire lifetime. Looking at your calling pattern, you should store them in an instance field of type List<FileSystemWatcher>.
Also your ExecuteAsync isn’t async, despite its name. You need to relinquish your thread at some point, by awaiting either Task.Delay(...) or Task.Yield() in your while loop.