【问题标题】:Best way to watch for files观看文件的最佳方式
【发布时间】:2013-04-10 11:58:04
【问题描述】:

好的,我有一个应用程序可以根据另一个应用程序创建的文件生成一些合同。

我已经实现了一个文件监视程序来监视正在创建的文件,然后它会启动一个backgroundworker 进程来根据文件名创建合同。

我遇到的问题是,在后台工作进程中,我将 EnableRaisingEvents 设置为 false,以便应用程序在第一个合同运行时不会开始处理另一组合同(这也是停止调用后台工作人员虽然它正在运行,因为它不能同时运行 2 个东西!)。

一切正常,另一个应用程序创建了一个文件,filewatcher 将其拾取并开始处理,问题是处理完成后,filewatcher 被重新启用,但我认为它不会拾取在 @ 时创建的任何文件987654323@ 是错误的 - 因此,如果创建初始文件以生成合同的应用程序碰巧在我的应用程序处理时创建了另一个文件,它将被留下。那有意义吗?最好的解决方法是什么?

我曾想过有另一个进程,当初始合同创建完成后,将在目录中查找在禁用文件监视程序时创建的其他文件,如果没有,则重新启用文件监视程序,但我想知道是否有更简单的方法可以做到这一点?

【问题讨论】:

  • 您可以将更改的文件排队到 List 或更好的 Queue 中,然后按顺序处理队列

标签: c# .net file-io


【解决方案1】:

您可以将流程拆分为任务。一项任务是 FileRegistrator ,它拾取新文件,将它们注册到数据库中。它一直在运行,无需将 EnableRaisingEvents 设置为 false。

下一个任务是 ProcessorTask(或任何名称),它将查询数据库,找到第一个并处理它。它会定期查询数据库,看看是否注册了新文件。

您可以在 Windows 服务中使用 Quartz.NET 调度程序来实现这个小处理器。

(前段时间我也做了差不多,但我没有使用 FileSystemWatcher)

【讨论】:

    【解决方案2】:

    BlockingCollection 可以做到这一点。
    保持 FileWatcher 热并让它添加到阻塞集合中。
    消费者一次只处理一个集合。

    BlockingCollection Class

    class AddTakeDemo
    {
        // Demonstrates: 
        //      BlockingCollection<T>.Add() 
        //      BlockingCollection<T>.Take() 
        //      BlockingCollection<T>.CompleteAdding() 
        public static void BC_AddTakeCompleteAdding()
        {
            // here you need to synch as it would have missed any 
            // new files while the application was down 
            // yes L-Three and any files that were not yet processed 
            // clearly the existing program is an end to end synch 
            // or no synch at all as it could be nothing else 
            using (BlockingCollection<int> bc = new BlockingCollection<int>())
            {
    
                // Spin up a Task to populate the BlockingCollection  
                using (Task t1 = Task.Factory.StartNew(() =>
                {
                    //  FielSystem watcher                    
                    bc.Add(fille);
    
                }))
                {
    
                    // Spin up a Task to consume the BlockingCollection 
                    using (Task t2 = Task.Factory.StartNew(() =>
                    {
                        try
                        {
                            // Consume consume the BlockingCollection 
                            while (true) Console.WriteLine(bc.Take());
                            // process the file
                        }
                        catch (InvalidOperationException)
                        {
                            // An InvalidOperationException means that Take() was called on a completed collection
                            Console.WriteLine("That's All!");
                        }
                    }))
    
                        Task.WaitAll(t1, t2);
                }
            }
        }
    }
    

    【讨论】:

    • @L-Three 我认为这个问题不需要持久性。
    • 不,这只是一个问题,因为我不知道这个问题。
    • @L-Three 不,它不是持久的,但是如果应用程序出现故障,它无论如何都需要在文件系统上进行新的同步,因为文件系统观察器不会捕获应用程序时发生的文件系统事件倒下了。
    • 小备注:如果有很多文件更改,并且有一个任务队列等待您的进程执行;并且系统崩溃。在这种情况下,您会丢失任务,因此系统将不可靠。
    • 最多只能说 5 或 6 个文件,所以这不是问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    • 2012-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多