如何在C#.NET中按顺序处理队列中的元素
我正在Visual Studio 2012中为Windows编写软件,代码为C 通过使用FileSystemWatcher类,我正在监视目录的更改:如果一个或多个新文件添加到目录中,FileSystemEventHandler类将触发一个事件 此事件将文件名添加到数组中 然后我想处理数组,也就是说:处理数组中的每个文件(通过文件名访问),并对文件进行处理 现在:我需要确保文件处理按顺序进行。查看文件1并对其进行处理,只有在完成后,才查看文件2并对其进行处理,依此类推 每个文件处理大约需要5秒钟。同时,可以将新文件添加到目录中,因此FileSystemEventHandler类将因这些更改而激发。但我不希望发生这种情况-每次应该只有一个文件得到处理-无论更改事件触发多少次如何在C#.NET中按顺序处理队列中的元素,c#,queue,filesystemwatcher,sequential,C#,Queue,Filesystemwatcher,Sequential,我正在Visual Studio 2012中为Windows编写软件,代码为C 通过使用FileSystemWatcher类,我正在监视目录的更改:如果一个或多个新文件添加到目录中,FileSystemEventHandler类将触发一个事件 此事件将文件名添加到数组中 然后我想处理数组,也就是说:处理数组中的每个文件(通过文件名访问),并对文件进行处理 现在:我需要确保文件处理按顺序进行。查看文件1并对其进行处理,只有在完成后,才查看文件2并对其进行处理,依此类推 每个文件处理大约需要5秒钟。
有人能为我提供一个模式(或代码片段)吗 您想要的模式是FileSystemEventHandler简单地将文件名添加到共享队列中 然后,另一个线程可以独立地监视该队列,然后该线程从队列中删除项目并对其进行处理 这样,在处理文件时就不需要“停止”事件处理程序添加项目。它可以继续添加更多,并且不会影响工作线程 我建议使用ConcurrentQueue类来管理要处理的文件列表 以下Microsoft的示例代码演示了如何使用BlockingCollection(包装ConcurrentQueue)来实现此目的:
您想要的模式是FileSystemEventHandler简单地将文件名添加到共享队列中 然后,另一个线程可以独立地监视该队列,然后该线程从队列中删除项目并对其进行处理 这样,在处理文件时就不需要“停止”事件处理程序添加项目。它可以继续添加更多,并且不会影响工作线程 我建议使用ConcurrentQueue类来管理要处理的文件列表 以下Microsoft的示例代码演示了如何使用BlockingCollection(包装ConcurrentQueue)来实现此目的:
我认为下面的课程是最好的
BlockingCollection
Class
为实现IProducerConsumerCollection的线程安全集合提供阻止和绑定功能
它充当并发队列,您可以使用任务异步处理项目
另一种选择是ConcurrentQueue
,但BlockingCollection提供了两个重要特性
它是线程安全的
当您调用
Take()
时,它将为您阻塞(即等待队列中有东西),因此您不必使用ManualResetEvents等编写任何代码,这是一个很好的简化。我认为下面的类将是最佳的
BlockingCollection
Class
为实现IProducerConsumerCollection的线程安全集合提供阻止和绑定功能
它充当并发队列,您可以使用任务异步处理项目
另一种选择是ConcurrentQueue
,但BlockingCollection提供了两个重要特性
它是线程安全的
当您调用Take()
时,它会为您阻塞(即等待队列中有东西),因此您不必使用ManualResetEvents等编写任何代码,这是一种很好的简化。您需要使用。
队列需要在单独的线程中处理。因此,您可以在不干扰您需要使用的监视文件夹事件的情况下处理文件数组列表。
队列需要在单独的线程中处理。因此,您可以在不干扰监视文件夹事件的情况下处理文件数组列表您可以设置一个布尔变量,如果另一个文件正在处理,该变量将设置为true,而在处理完成后将设置为false。同时,如果FileSystemEventHandler触发一个新事件,它将检查该变量,如果该变量设置为true,它将等待。否则,将变量设置为true本身和carryon。您可以设置一个布尔变量,如果另一个文件正在处理,则该变量设置为true,而在处理完成后设置为false。同时,如果FileSystemEventHandler触发一个新事件,它将检查该变量,如果该变量设置为true,它将等待。否则,将变量本身设置为true,并将其带入。您也可以选择使用 大概是这样的:
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));
}
publicstatictuple-Watch(此字符串路径,actionprocessnewfile)
{
var-watcher=newfilesystemwatcher(path){EnableRaisingEvents=true};
返回
Tuple.Create(
观察者,
可观察
.FromEventPattern(
handler=>watcher.Created+=handler,
handler=>watcher.Created-=handler)
.Select(模式=>pattern.EventArgs.FullPath)
.ForEachAsync(processNewFile));
}
这种方法异步友好、简洁,无需编写大量样板代码。您也可以选择使用 大概是这样的:
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));
}
publicstatictuple-Watch(此字符串路径,actionprocessnewfile)
{
var-watcher=newfilesystemwatcher(path){EnableRaisingEvents=true};
返回
Tuple.Create(
观察者,
可观察
.FromEventPattern(
handler=>watcher.Created+=handler,
handler=>watcher.Created-=handler)
.Select(模式=>pattern.EventArgs.FullPath)
.ForEachAsync(processNewFile));
}
这种方法是可行的