简体   繁体   English

观看文件的最佳方法

[英]Best way to watch for files

OK I have an application that produces some contracts based on a file that is created by another app. 好的,我有一个应用程序可以根据另一个应用程序创建的文件生成一些合同。

I have implemented a filewatcher to watch for the file being created and it then kicks off a backgroundworker process to create the contracts based on the filename. 我已经实现了一个文件监视程序来监视正在创建的文件,然后它启动了一个backgroundworker程序进程来基于文件名创建合同。

The problem I am having is that during the background worker process I set EnableRaisingEvents to false so that the app does not start to process a different set of contracts whilst the first is running (It's also to stop calling the background worker whilst it is running as it cant run 2 things at once!). 我遇到的问题是,在后台工作程序进程中,我将EnableRaisingEvents设置为false,以使应用程序在第一个运行时不会开始处理一组不同的合同(也正在以以下方式运行时停止调用后台工作程序:它不能一次运行2件事!)。

All works fine, the other app creates a file, filewatcher picks it up and starts processing, the problem is that when processing is finished the filewatcher is re-enabled but I assume it wont pick up any files that were created when EnableRaisingEvents was false - and so if the application that creates the initial file to produce the contracts happens to create another file whilst my app is processing it will just be left. 一切正常,另一个应用程序创建了一个文件,filewatcher拾取了该文件并开始处理,问题是当处理完成时,filewatcher被重新启用,但是我认为它不会拾取EnableRaisingEvents为false时创建的任何文件-因此,如果创建初始文件以产生合同的应用程序恰好在我的应用程序正在处理时创建了另一个文件,则该文件将被保留。 Does that make sense? 那有意义吗? And what is the best way round this? 最好的解决方法是什么?

I had thought of having another process that when the initial contract creation is finished would then look in the directory for other files created between the time when the filewatcher was disabled and if there were none it would then re-enable the filewatcher but I am wondering if there is a simpler way to do this? 我曾考虑过另一个过程,当初始合同创建完成时,将在目录中查找在禁用文件监视程序的时间之间创建的其他文件,如果没有,则将重新启用文件监视程序,但是我想知道是否有更简单的方法可以做到这一点?

You could split your process in tasks. 您可以将流程分为多个任务。 One task is the FileRegistrator , which picks up new files, registers them in database. FileRegistrator是一项任务,它拾取新文件,并将其注册到数据库中。 It runs all the time, no need to EnableRaisingEvents to false. 它始终运行,无需将EnableRaisingEvents设置为false。

The next task is the ProcessorTask (or whatever name) which will query the database, find the first one and processes it. 下一个任务是ProcessorTask(或任何名称),它将查询数据库,找到第一个数据库并进行处理。 It will query the database at regular times to see if a new file is registered. 它将定期查询数据库,以查看是否已注册新文件。

You could implement this little processor using Quartz.NET scheduler in a windows service. 您可以在Windows服务中使用Quartz.NET调度程序来实现这个小的处理器。

(I did about the same a while ago, but I didn't use FileSystemWatcher) (前一阵子我做的差不多,但是我没有使用FileSystemWatcher)

A BlockingCollection would do this. 一个BlockingCollection可以做到这一点。
Keep FileWatcher hot and let it add to the blocking collection. 保持FileWatcher处于高温状态,然后将其添加到阻止集合中。
The consumer just processes the collection one at a time. 消费者一次只处理一个集合。

BlockingCollection Class BlockingCollection类

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);
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM