繁体   English   中英

程序设计问题,filesystemwatcher,多线程c#

[英]Program design issue , filesystemwatcher, multithreading c#

我正在开发ac#程序,它使用FilesystemWatcher来监视添加到monitor_directory中的PDF文件。 每次将文件添加到目录时,我都会将其添加到另一个线程无限循环中连续弹出的BlockingQueue,它会等待添加文件路径,之后我继续处理文件,最后一部分PDF文件处理正在将其移动到输出目录。

调度线程:

    private static void ThreadProc(object param)
    {

        FileMonitorManager _this = (FileMonitorManager)param;
        FileProcessingManager processingManager = new FileProcessingManager();
        processingManager.RegisterProcessor(new ExcelFileProcessor());
        processingManager.RegisterProcessor(new PdfFileProcessor());

        while (true)
        {
            try
            {
                var path = (string)_this.FileQueue.Dequeue();
                if (path == null)
                    break;
                bool b = processingManager.Process(path);
                if (!b)
                {
                    _this.FileQueue.Enqueue(path);
                    Console.WriteLine("\n\nError on file: " + path);
                }
                else
                    Console.WriteLine("\n\nSucces on file: " + path);

            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }

Process函数测试文件是否存在,进行一些处理并将PDF文件移动到输出目录。

我遇到了两个问题:1。来自FileSystemWatcher的On_Create事件处理程序被触发TWICE,因此BlockingQueue具有相同的两次条目,在这种情况下,在处理例程中我验证文件是否尚未移动到输出目录(因为这是处理的最后部分包括在那里移动文件),如果是这样我继续进行处理,如果没有我退出。 2.如果由于某种原因我得到一个错误,访问文件的内容说:该文件正由另一个进程使用我从Process函数返回FALSE并再次将文件路径添加到队列。

现在..这有效,但它有点慢..我怎么能通过考虑我面临的两个问题来做多线程.. 编辑:如果我得到事件,将其添加到队列,它被弹出,队列是空的然后我再次获得相同的事件,队列是空的,所以它被添加,基本上我得到相同的事件处理TWICE?

众所周知,FileSystemWatcher很健谈。

我想这就是我要做的......

  1. 在On_Create调用中再次添加第二次之前,请检查BlockingQueue是否已有相关文件的条目。
  2. 你期望你的队列中有很多空路径吗? 希望空检查只是一个预防措施。 但是,如果你可以帮助它,不要排队空路径。
  3. 在你的工作线程中只需Dequeue和process
  4. 如果您的工作线程处理错误,您可以再次将其排队,或者您可能希望将其置于一个例外情况,因为如果您获得足够的不可处理文件,他们可能会占用您的队列并减慢您的速度。

执行此多线程的一种简单方法是每次出列路径时启动一个新任务...

    Task.Factory.StartNew(() =>
        {
            try
            {
                var path = (string) _this.FileQueue.Dequeue();
                if (path == null)
                    break;
                bool b = processingManager.Process(path);
                if (!b)
                {
                    _this.FileQueue.Enqueue(path);
                    Console.WriteLine("\n\nError on file: " + path);
                }
                else
                    Console.WriteLine("\n\nSucces on file: " + path);

            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
            }
        });

对于生产代码,您还需要将取消令牌传递给任务,并具有停止循环和任务的机制。

1) FileSystemWatcher通知您两次,因为文件分两步更新:首先是数据 ,然后是元数据 因此,您可以使用以下内容检查最新的写入是否已被考虑在内:

File.GetLastWriteTime(file);

或者您可以检查重复项。

2)你没有使用多线程:你一次处理一个文件,所以你可以产生一些线程来执行Process方法,例如使用:

ThreadPool.QueueUserWorkItem

暂无
暂无

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

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