C# Loop 方法每分钟,它的文件存在做一些事情,如果不等到它被创建

C# Loop method every minute, it file exist do something, if not wait untill its created

我有一个程序可以检查是否创建了 .csv 文件。如果创建了,就做一些事情,如果没有等到它创建。在 C# 中可以吗?

尝试过类似的方法但效果不佳...

        var startTimeSpan = TimeSpan.Zero;
        var periodTimeSpan = TimeSpan.FromMinutes(1);

        var timer = new System.Threading.Timer((e) =>
        {
            if (!File.Exists(@"TestFileLocation"))
        {
            MethodName(); //Tried this to start method agian
        }
        else
        {
            HereIsRestOfTheCodeToDoSomeActions();
        }
        }, null, startTimeSpan, periodTimeSpan);

如果我的 post 不够清楚,抱歉我英语不流利,下面是步骤,程序将如何运行:

  1. 检查文件夹中是否创建了文件
  2. 如果没有,等1分钟再检查
  3. 如果文件被创建做一些事情
  4. 从头开始循环此步骤

创建 FileSystemWatcher https://docs.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher?view=net-6.0 并在 OnCreated

中添加检查

最适合您的问题的方法是使用 FileSystemWatcher。它的工作是监视目录的变化,例如在您的问题中需要它时创建文件。

这也会使 one-minute-threshold 过时。考虑例如:

// necessary assembly using for using FileSystemWatcher classes.
using System.IO;

// ...

// instantiate your watcher.
using var watcher = new FileSystemWatcher(@"C:\path\to\folder");

// just filter for interesting attribtes.
watcher.NotifyFilter = NotifyFilters.FileName;

// attach an event handler to the event that is triggered when a file is created.
watcher.Created += OnCreated;

// ...

// implement the event handler.
private static void OnCreated(object sender, FileSystemEventArgs e)
{
    // if the name is "your" name, you're ready to go ...
    if (e.Name == "my_name")
        // do something ...

}

但是,如果您仍想使用循环(由于您未在 post 中说明的限制),那么它可能类似于以下 less adorable 方法:

var now = DateTime.Now;
var waitTime = TimeSpan.FromMinutes(1);
    
while (true)
{
    if (!File.Exists(@"TestFileLocation"))
    {
        // do something ...
            
        // exit the loop.
        break;
    }
        
    Thread.Sleep(waitTime);
}

注意并注意这个endless-loop会阻塞主线程,直到您找到您的文件。更好的方法是在主线程之外的单独线程中执行该任务。

除了将代码包装到 class 之外,此代码与 @markwellman 相同。代码不会等待,它会持续监控并且看不出停止和启动的原因。

在下面的示例中,在 FileOperations

的构造函数中传递要监视的文件夹和要监视的文件文件名
using System;
using System.IO;
using static System.IO.Path;

namespace YourNamespace
{
    public class FileOperations : FileSystemWatcher
    {
        /// <summary>
        /// Path to check for file
        /// </summary>
        public string MonitorPath { get; set; }
        /// <summary>
        /// File name to watch for
        /// </summary>
        public string FileName { get; set; }
        
        public FileOperations(string monitorPath, string fileName)
        {
            if (!Directory.Exists(monitorPath))
            {
                throw new Exception($"Missing {monitorPath}");
            }

            MonitorPath = monitorPath;

            Created += OnCreated;

            Path = MonitorPath;
            Filter = fileName;
            FileName = fileName;
            EnableRaisingEvents = true;
            NotifyFilter = NotifyFilters.FileName;
        }

        private void OnCreated(object sender, FileSystemEventArgs e)
        {
            var fileName = Combine(MonitorPath, GetFileName(e.FullPath));
            
            if (fileName.Equals(Combine(MonitorPath,FileName), StringComparison.OrdinalIgnoreCase))
            {
                // TODO
            }
        }
        public void Start()
        {
            EnableRaisingEvents = true;
        }
        public void Stop()
        {
            EnableRaisingEvents = false;
        }
    }
}

然后在表单中创建 FileOperations 的私有实例。在窗体关闭事件中调用 Stop 方法。

public partial class Form1 : Form
{
    private readonly FileOperations _fileOperations =
        new FileOperations("Path to watch", "file name to trigger on");
    public Form1()
    {
        InitializeComponent();

        Closing += OnClosing;
    }

    private void OnClosing(object sender, CancelEventArgs e)
    {
        _fileOperations.Stop();
    }
}