I am trying to make a program that watches a folder for file creation events and does some processing on the files. My current implementation works using:
FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();
fileSystemWatcher.Created += FileSystemWatcher_Created;
However, this seems to have memory leaks. Each time FileSystemWatcher_Created
is called, the garbage collector does not dispose of it when it is done. I think that every instance of FileSystemWatcher_Created
cannot be disposed of while the original FileSystemWatcher
object still exists.
I don't think using fileSystemWatcher.Created -= FileSystemWatcher_Created;
helps me in this case because I don't want FileSystemWatcher_Created
to run only once. I want FileSystemWatcher_Created
to run every time the file creation event happens. I just want the garbage collector to properly dispose of the memory that is used up for each instance.
I think this means that I want to use a WeakEventHandler
to handle the event right? How do I do that in this context? I am using .NET Core
but would still appreciate any .NET Framework
answers.
Edit to add: FileSystemWatcher_Created
. I am running a PowerShell script on the detected file and then moving it after processing.
private void FileSystemWatcher_Created(object sender, FileSystemEventArgs e)
{
//Get FileInfo object for newly detected file
FileInfo file = new FileInfo(e.FullPath);
//Wait until the file is able to be accessed
while (IsFileLocked(file))
{
//If file is locked then wait 5 seconds and try again
Thread.Sleep(5000);
}
//Run PowerShell script from PowerShell_Script_Path with the operation, CSV filepath, and EXE filepath as arguments
ps.AddScript(File.ReadAllText(PowerShell_Script_Path)).AddArgument(GetOperation(e.Name)).AddArgument(e.FullPath).AddArgument(GetPath(Test_Mode)).Invoke();
//Wait until the file is able to be accessed
while (IsFileLocked(file))
{
//If file is locked then wait 10 seconds and try again
Thread.Sleep(10000);
}
//Move file from pending folder to archive folder
File.Move(e.FullPath, $"{Dst_Path}/{e.Name}", true);
}
After some trial and error, I get the least memory leaks by subscribing to the event with an anonymous function.
//Set File Watch File Creation Event Handler
fileSystemWatcher.Created += (object sender, FileSystemEventArgs e) =>
{
//Get FileInfo object for newly detected file
FileInfo file = new FileInfo(e.FullPath);
//Wait until the file is able to be accessed
while (IsFileLocked(file))
{
//If file is locked then wait 5 seconds and try again
Thread.Sleep(5000);
}
//Run PowerShell script from PowerShell_Script_Path with the operation, CSV filepath, and EXE filepath as arguments
ps.AddScript(File.ReadAllText(PowerShell_Script_Path)).AddArgument(GetOperation(e.Name)).AddArgument(e.FullPath).AddArgument(GetPath(Test_Mode)).Invoke();
//Wait until the file is able to be accessed
while (IsFileLocked(file))
{
//If file is locked then wait 10 seconds and try again
Thread.Sleep(10000);
}
//Move file from pending folder to archive folder
File.Move(e.FullPath, $"{Dst_Path}/{e.Name}", true);
}