I have below program where StartFileWatcher
looking into a folder (C:\TEMP
) (including subdirectories) and copying all the files info to the C# channel
based of file LastWriteTimeUtc
and having some logic to compare.
This works most of the case (all the files processing in order by lastwritetime
) where copy is immediately completes to the folder C:\TEMP
, otherwise order fails.
In my code I am doing some manual adjustment of delay (await Task.Delay(5000, cancellationToken);
), if within 5000
ms, the entire copy is done, then processing of files happens in order, otherwise not.
Question is, rather than manual delay adjustments can I notify FileSystemWatcher
to start work once copy is completed?
Main:
static async Task Main(string[] args)
{
string folderPath = @"C:\TEMP";
CancellationTokenSource cts = new CancellationTokenSource();
Channel<string> fileChannel = Channel.CreateUnbounded<string>();
// Start the file watcher
Task watcherTask = StartFileWatcher(
folderPath, fileChannel.Writer, cts.Token);
// Start processing files
Task processingTask = ProcessFilesAsync(
fileChannel.Reader, cts.Token);
// Wait for user input to stop
Console.WriteLine("Press Enter to stop...");
Console.ReadLine();
// Cancel the tasks
cts.Cancel();
// Wait for the tasks to complete
await Task.WhenAll(watcherTask, processingTask);
Console.WriteLine("Program stopped.");
}
StartFileWatcher:
static async Task StartFileWatcher(
string folderPath,
ChannelWriter<string> channelWriter,
CancellationToken cancellationToken)
{
using (var watcher = new FileSystemWatcher(folderPath))
{
List<string> pendingFiles = new List<string>();
watcher.IncludeSubdirectories = true;
watcher.Created += (sender, e) =>
{
if (!e.Name.StartsWith("~"))
{
lock (pendingFiles)
{
pendingFiles.Add(e.FullPath);
pendingFiles.Sort((a, b) =>
File.GetLastWriteTimeUtc(a)
.CompareTo(File.GetLastWriteTimeUtc(b)));
}
}
};
watcher.EnableRaisingEvents = true;
while (!cancellationToken.IsCancellationRequested)
{
List<string> filesToProcess;
lock (pendingFiles)
{
filesToProcess = new List<string>(pendingFiles);
pendingFiles.Clear();
}
foreach (var filePath in filesToProcess)
{
channelWriter.TryWrite(filePath);
}
// Adjust the delay as needed
await Task.Delay(5000, cancellationToken);
}
}
}
ProcessFilesAsync:
static async Task ProcessFilesAsync(
ChannelReader<string> channelReader,
CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
if (await channelReader.WaitToReadAsync(cancellationToken))
{
while (channelReader.TryRead(out string filePath))
{
Console.WriteLine($"file: {filePath}," +
$"LastWriteTime: " +
$"{new FileInfo(filePath).LastWriteTime}");
// Simulate processing delay
await Task.Delay(2000, cancellationToken);
}
}
}
}