0

私の仕事は、処理が完了したらファイルを削除することです。このタスクを完了するために FileWatcher を使用しています。特定のフォルダを監視しています。1つのファイルをコピーしてそれをfilewatcherフォルダーに入れると、それが削除されているとします。2 回目は、同じファイルをコピーして、同じ監視フォルダーに貼り付けます。今回は、別のプロセスがそのファイルを使用していますと表示されます。そして例外は投げています。私は何かが欠けていると思います。これが私のコードです

private static void Main(string[] args)
    {

       var fw = new FileSystemWatcher(EmailSetting.DataFolder)
        {
            IncludeSubdirectories = false
            ,
            EnableRaisingEvents = true

        };
        fw.Created += (sender, e) =>
        {
         File.Delete(e.FullPath);

        };
        Console.ReadLine();
    }
4

1 に答える 1

1

ファイルが作成されたときに Created イベントを受け取ります (名前の由来)。しかし、この時点で、実際にそれを作成している他のプロセスは、そのファイルへのコンテンツの書き込みを完了していません。したがって、ファイルは既にそこにある可能性がありますが、他のファイルはまだ作業中です (8 GB のファイルをコピーするとします)。

ファイルのパスをイベント内のリストに単純に書き込み、別のスレッドがこの並行バッグを定期的に (たとえば 1 秒に 1 回) チェックするようにする方が賢明です。まず、ファイルが存在するかどうかを確認し、存在する場合は削除を試みます。成功した場合はバッグから取り出し、失敗した場合は次回に再試行します。

コード例

private static readonly ConcurrentQueue<FileInfo> _FileCandidates = new ConcurrentQueue<FileInfo>();

private static void Main(string[] args)
{
    var watcher = new FileSystemWatcher
    {
        Path = @"R:\TestFolder",
        IncludeSubdirectories = false,
        Filter = "*.*",
    };

    Console.WriteLine("Start watching folder... " + watcher.Path);
    watcher.Created += OnFileCreated;
    watcher.EnableRaisingEvents = true;

    var timer = new Timer
    {
        AutoReset = true,
        Interval = 1000,
    };

    timer.Elapsed += OnTimerElapsed;
    timer.Enabled = true;

    Console.ReadKey();
}

static void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
    FileInfo file;
    var stillInUseFiles = new List<FileInfo>();

    Console.WriteLine("Check for file candidates...");
    while (_FileCandidates.TryDequeue(out file))
    {
        try
        {
            Console.WriteLine("Delete " + file.FullName);

            if (file.Exists)
                file.Delete();
        }
        catch (IOException)
        {
            Console.WriteLine("Could not delete file, try again next time.");
            stillInUseFiles.Add(file);
        }
    }

    foreach (var unhappyFile in stillInUseFiles)
    {
        _FileCandidates.Enqueue(unhappyFile);
    }
}

static void OnFileCreated(object sender, FileSystemEventArgs e)
{
    Console.WriteLine("Found new file candidate " + e.FullPath);
    _FileCandidates.Enqueue(new FileInfo(e.FullPath));
}
于 2015-12-17T13:30:00.380 に答える