C# Use Weak Event For FileSystemWatcher.Created Event

130 Views Asked by At

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);
}
               
0

There are 0 best solutions below