I'm trying to create an application in Net 5 that watches a folder and any time files are being dropped in the folder, it should run a certain set of tasks (getting some info from the files, copy them to new location, among others).
I thought I could implement both Net's FileSystemWatcher
and concurrent collections (from the Collections.Concurrent
namespace here, but I run into the problem that I cannot run it with being async.
I initialize the watcher like this (following the docs of MS):
public BlockingCollection<string> fileNames = new BlockingCollection<string>();
public void InitiateWatcher()
{
using FileSystemWatcher watcher = new FileSystemWatcher(@"C:\temp"); //test dir
watcher.NotifyFilter = NotifyFilters.Attributes
| NotifyFilters.CreationTime
| NotifyFilters.DirectoryName
| NotifyFilters.FileName
watcher.Created += OnCreated;
watcher.Filter = "*.*";
watcher.IncludeSubdirectories = true;
watcher.EnableRaisingEvents = true;
Console.WriteLine("Press e to exit.");
Console.ReadLine();
}
private void OnCreated(object sender, FileSystemEventArgs e)
{
string value = $"Created: {e.FullPath}";
// this of course creates problems, since it is a async task running in sync mode.
await PipelineStages.ReadFilenamesAsync(_sourcePath, fileNames);
// do other work with the result from ReadFilenameAsync
Console.WriteLine(value);
}
My PipelineStages class, which does most of the real work with the files, looks like this:
public static class PipelineStages
{
public static Task ReadFilenamesAsync(string path, BlockingCollection<string> output)
{
return Task.Factory.StartNew(() =>
{
foreach (string fileName in Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories))
{
output.Add(fileName);
}
output.CompleteAdding();
}, TaskCreationOptions.LongRunning);
}
}
If I turn the OnCreated method async it throws error that the return type is not valid. That kinda makes sense to me, although I don't know the way forward on this.
I see two errors:
One error is when the code hits the output.add(fileName)
line, it throws an System.InvalidOperationException: 'The collection has been marked as complete with regards to additions.'
The other one is that I notice in the onCreated method that filenames get written to the console that are in very different folders, seemingly randomly.
So, basically, I have two questions:
- Is this the right approach? (If not, what are other alternatives)
- If this is the right approach, how can I fix these problems?