Reputation: 2822
I was trying to detect a file in a folder using Filewatcher and move the file to a new location. While doing so using a console application, I am getting error as The process cannot access the file because it is being used by another process
.
I am getting this error at File.Move(f.FullName, System.IO.Path.Combine(@"C:\Users\ADMIN\Downloads\FW_Dest", Path.GetFileName(f.FullName)));
in the OnChanged
method.
Please check the below code and help me with this issue. Thanks in advance.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.Permissions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Run();
}
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public static void Run()
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = @"C:\Users\ADMIN\Downloads\FW_Source";
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
watcher.Filter = "*.*";
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
}
private static void OnChanged(object source, FileSystemEventArgs e)
{
DirectoryInfo directory = new DirectoryInfo(@"C:\Users\ADMIN\Downloads\FW_Source\");
FileInfo[] files = directory.GetFiles("*.*");
foreach (var f in files)
{
File.Move(f.FullName, System.IO.Path.Combine(@"C:\Users\ADMIN\Downloads\FW_Dest", Path.GetFileName(f.FullName)));
}
}
}
}
Upvotes: 0
Views: 4354
Reputation: 123
I ran into this problem with larger files being moved into the watched folders.
I called the IsLocked
method in my OnChange
method and don't move past it till it returns false.
while (IsFileLocked(ImportFormat.FileName)) {
//Do nothing until the file is finished writing
}
IsLocked Method:
/// <summary>
/// Tries to open the file for R/W to see if its lock. Returns Boolean
/// </summary>
/// <param name="filePath"></param>
/// <returns>bool</returns>
protected static bool IsFileLocked(string filePath) {
FileStream stream = null;
var file = new FileInfo(filePath);
try {
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}catch (IOException err) {
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
} finally {
stream?.Close();
}
//file is not locked
return false;
}
Upvotes: 0
Reputation: 65421
Instead of moving all the files in the watched folder, just move the file which was created, like so:
private static void OnChanged(object source, FileSystemEventArgs e)
{
File.Move(e.FullPath, Path.Combine(@"C:\Users\ADMIN\Downloads\FW_Dest", e.Name));
}
A better way than Thread.Sleep(2000)
to wait 2 seconds would be as follows:
private static async void OnChanged(object source, FileSystemEventArgs e)
{
await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
File.Move(e.FullPath, Path.Combine(targetFolder, e.Name));
}
This would prevent the program from locking multiple threads if many files are copied in sinultaneously.
Upvotes: 2
Reputation: 39013
You're getting the Changed
event while the file is being changed. You're trying to move it before the process writing to the file is done. I
suggest you first try to open the file exclusively (deny read, deny write), and only when you succeed close it and move the file. If you don't succeed, wait a few seconds and try again.
Upvotes: 6