如何在 C# .NET 中按顺序处理队列中的元素
本文关键字:顺序处理 队列 元素 NET | 更新日期: 2023-09-27 18:36:25
我正在用Visual Studio 2012编写Windows软件,用C#编码。
通过使用 FileSystemWatcher 类,我正在监视目录的更改:如果将一个或多个新文件添加到该目录中,则 FileSystemEventHandler 类会触发一个事件。
此事件将文件名添加到数组中。
然后我想处理数组,即:处理数组中的每个文件(通过文件名访问)并对文件执行某些操作。
现在:我需要确保文件处理按顺序进行。查看文件 1,处理它,只有当它完成后,查看文件 2,处理它,依此类推。
每个文件的文件处理大约需要 5 秒。同时,可以将新文件添加到目录中,因此 FileSystemEventHandler 类将因为这些更改而触发。但我不希望这种情况发生 - 一次应该只有一个文件被处理 - 无论更改事件被触发多少次!
任何人都可以为我提供一个模式(或代码片段)吗?!
我认为跟随类将是最佳的,
BlockingCollection<T>
类
为实现 IProducerConsumerCollection 的线程安全集合提供阻塞和绑定功能。
它充当并发队列,您可以使用任务异步处理项目。
替代方案是ConcurrentQueue<T>
,但阻止集合为您提供了两个重要功能
它是线程安全的
当你调用Take()
时,它会为你阻塞(即等到队列中有东西),所以你不必用ManualResetEvents等编写任何代码,这是一个很好的简化。
您也可以选择使用 RX 框架。
像这样:
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));
}
这种方法是异步友好的,简洁的,并且不需要编写大量样板代码。
您想要的模式是 FileSystemEventHandler 只需将文件名添加到共享队列。
然后,另一个线程可以独立监视此队列,然后从队列中删除项目并处理它们。
这样,就无需在处理文件时"停止"事件处理程序添加项。它可以继续添加更多内容,并且不会影响工作线程。
我会建议像ConcurrentQueue类这样的东西来管理要处理的文件列表。
以下 Microsoft 示例代码演示如何使用 BlockingCollection(包装 ConcurrentQueue)来实现此目的:
http://msdn.microsoft.com/en-us/library/dd997371.aspx
您需要使用 队列 。队列需要在单独的线程中处理。因此,您可以在不干扰监视文件夹事件的情况下处理文件数组列表
设置一个布尔变量,如果另一个文件正在处理,则将其设置为 true,在完成处理后设置为 false。同时,如果 FileSystemEventHandler 触发一个新事件,它会检查该变量,如果设置为 true,它将等待。否则,将变量本身设置为 true 并继续。