【问题标题】:C# Daemon for reading large amount of files [duplicate]用于读取大量文件的 C# 守护进程 [重复]
【发布时间】:2016-03-23 13:33:54
【问题描述】:

我将首先给出一些上下文

简介

我正在创建一个将在服务器上连续运行的程序。该计划的一部分是能够向不同的代表发送自动邮件。这些邮件的内容会自动放在一个文件夹中,因此当新内容准备好时需要通知程序并读取该文件中的文本。不过这不是问题,我已经有了解决方案。

问题

文件夹中可能会同时放置多个文件,这是我的程序无法处理的情况。我得到以下异常:

System.IO.IOException: 进程无法访问文件 GENERATEDFILE 因为它正被另一个进程使用。

一旦程序尝试读取已放入文件夹中的文件,它就会给我这个异常,我无法理解为什么会这样

我已经拥有的

所以我有一个方法可以像这样创建 FileSystemWatcher:

public void Watch(){
_watcher = new FileSystemWatcher();
_watcher.NotifyFilters =  NotifyFilters.LastAccess |
                          NotifyFilters.LastWrite |
                          NotifyFilters.FileName |
                          NotifyFilters.DirectoryName;
_watcher.Created += OnCreated

}

private void OnCreated(object sender, FileSystemEventArgs e){
//read the file that got created here and pass the content to an object that wille handle it further
}

非常简单,我们创建了一个 FileSystemWatcher,我们为其附加了一些 NotifyFilters 和 OnCreated 事件

我已经尝试了以下

在 OnCreated 方法中我尝试了以下方法

  1. File.ReadAllText(filePath) 我认为这是读取文件的标准方式,但这不起作用
  2. using (StreamReader sr = new StreamReader(filePath)){ String line = sr.ReadToEnd();} 来自微软
  3. 我试过Thread.Sleep(5000)看是否需要一些时间,没有效果
  4. 我试过使用ReaderWriterLockSlim类,每次开始阅读时都会进入readlock,这个解决方案有时有效,但不足以保证
  5. 我尝试将每个文件放入一个列表中,然后遍历该列表,但仍然给我同样的异常

问题

有没有办法处理多个文件同时放入文件夹的事件?

【问题讨论】:

标签: c# multithreading file filesystemwatcher


【解决方案1】:

捕获异常并设置一个计时器稍后重试如何?

【讨论】:

    【解决方案2】:

    原因
    文件创建事件在文件创建时发生,而不是在完成写出时发生。

    解决方案
    考虑为处理逻辑添加一个任务。
    创建文件时,文件名/路径会传递给在不断重试的任务中运行的方法。

    using System;
    using System.Collections.Concurrent;
    using System.IO;
    using System.Threading.Tasks;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    
    namespace UnitTestProject1
    {
        [TestClass]
        public class UnitTest1
        {
            private ConcurrentQueue<string> _filesProcessQueue;
            private FileSystemWatcher _watcher;
    
            [TestMethod]
            public void Watch()
            {
                _filesProcessQueue = new ConcurrentQueue<string>();
                _watcher = new FileSystemWatcher
                {
                    NotifyFilter = NotifyFilters.LastAccess |
                                   NotifyFilters.LastWrite |
                                   NotifyFilters.FileName |
                                   NotifyFilters.DirectoryName
                };
                _watcher.Created += OnCreated;
            }
    
            private void OnCreated(object sender, FileSystemEventArgs e)
            {
                // Create a task for reading the file after the lock is released
                Task.Run(() => ProcessFileQueue(e.FullPath));
            }
    
            private void ProcessFileQueue(string fullPath)
            {
                bool processSuccess = false;
                // TODO put terminator logic in here to stop retrying forever
                while (processSuccess == false)
                {
                    // TODO try process the file and return success/fail
                    processSuccess = true; // Continue to next file
                    //processSuccess = false; // Retry the same file
    
                    Task.Delay(TimeSpan.FromSeconds(5)); // Delay 5 seconds before retrying the file.
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-20
      • 2016-12-21
      • 1970-01-01
      • 2013-06-17
      • 1970-01-01
      • 2023-03-02
      • 2014-08-30
      • 1970-01-01
      相关资源
      最近更新 更多