如何在C#.NET中顺序处理队列中的元素

时间:2013-10-22 07:29:20

标签: c# queue filesystemwatcher sequential

我在Visual Studio 2012中编写Windows软件,用C#编码。

通过使用FileSystemWatcher类,我正在监视目录中的更改:如果将一个或多个新文件添加到目录,则会由FileSystemEventHandler类触发事件。

此事件将文件名添加到数组中。

然后我想处理数组,即:处理数组中的每个文件(通过文件名访问)并对文件执行某些操作。

现在:我需要确保文件处理按顺序进行。查看文件1,处理它,只有在完成后,查看文件2,处理它,依此类推。

每个文件的文件处理大约需要5秒。同时,可以将新文件添加到目录中,因此FileSystemEventHandler类将因为这些更改而触发。但我不希望这种情况发生 - 应该始终只有一个文件被处理 - 无论更改事件被触发多少次!

有人可以为我提供一个模式(或代码片段)吗?!

5 个答案:

答案 0 :(得分:2)

我认为下课是最佳的,

BlockingCollection<T>

为实现IProducerConsumerCollection的线程安全集合提供阻塞和绑定功能。

它充当并发队列,您可以使用任务处理项目异步。

替代方案是ConcurrentQueue<T>,但BlockingCollection为您提供了两个重要功能

这是线程安全的

当你调用Take()时,它会阻塞(即等到队列中的某些东西),所以你不必用ManualResetEvents等编写任何代码,这是一个很好的简化。

答案 1 :(得分:1)

您想要的模式是FileSystemEventHandler只是将文件名添加到共享队列的模式。

然后,另一个线程可以独立监视此队列,然后从队列中删除项目并处理它们。

这样,在处理文件时,不需要“停止”事件处理程序添加项目。它可以继续添加更多,并且不会影响工作线程。

我建议像ConcurrentQueue类那样管理你要处理的文件列表。

Microsoft的以下示例代码显示了如何使用BlockingCollection(包装ConcurrentQueue)来实现此目的:

http://msdn.microsoft.com/en-us/library/dd997371.aspx

答案 2 :(得分:1)

您也可以选择使用RX framework

这样的事情:

public static Tuple<FileSystemWatcher, Task> Watch(this string path, Action<string> processNewFile)
{
    var watcher = new FileSystemWatcher(path) {EnableRaisingEvents = true};
    return
        Tuple.Create(
            watcher,
            Observable
                .FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
                    handler => watcher.Created += handler,
                    handler => watcher.Created -= handler)
                .Select(pattern => pattern.EventArgs.FullPath)
                .ForEachAsync(processNewFile));
}

这种方法 async 友好,简洁,无需编写大量样板代码。

答案 3 :(得分:0)

您需要使用Queue。 队列需要在一个单独的线程中处理。这样您就可以处理文件数组列表而不会干扰监视文件夹事件

答案 4 :(得分:0)

您可以设置一个布尔变量,如果另一个文件正在处理,则设置为true,在完成处理后设置为false。同时,如果FileSystemEventHandler触发一个新事件,它会检查该变量,如果设置为true,则该变量将等待。否则,将变量本身设置为true并继承。