我做了一个服务来监视文件夹以查看何时添加新文件。当添加新文件时,将文件按行分解(每行存储在一个列表中),然后将每行存储的数据编码成二维码图像。 QR 图像随后会保存到一个新文件夹中。整个过程有效,但是当我同时将多个文件放入一个文件夹时,我的服务只对其中一个文件的行进行了编码。
问题:我如何创建一个队列来将新添加的文件(当一次放入多个文件时)存储在一个列表中,一旦它对队列中的当前文件进行编码,我就可以从列表中提取??
首先,我正在使用 System.Collections.Concurrent 队列创建一个方法来获取队列中的数据。
观察者方法: 启动服务/文件系统监视器
public void Start()
{
newfolders = ConfigurationManager.AppSettings["parsefiles"];
pathtomonitor = ConfigurationManager.AppSettings["pathtomonitor"];
pathforpaths = newfolders;
System.IO.Directory.CreateDirectory(pathforpaths);
Thread.Sleep(2000);
pathforprocess = newfolders + @"\processdata";
System.IO.Directory.CreateDirectory(pathtomonitor);
System.IO.Directory.CreateDirectory(pathforprocess);
FileSystemWatcher watcher = new FileSystemWatcher(pathtomonitor);
watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.FileName;
watcher.EnableRaisingEvents = true;
watcher.IncludeSubdirectories = false;
//add event handlers
watcher.Created += watcher_Created;
}
将文件添加到文件夹并创建二维码
private static void watcher_Created(object sender, FileSystemEventArgs e)
{
if (e.ChangeType == WatcherChangeTypes.Created)
{
if (DateTime.Now.Subtract(_lastTimeFileWatcherEventRaised)
.TotalMilliseconds < 1000)
{
Console.WriteLine("Short time between previous event and change event");
return;
}
Console.WriteLine("file: {0} changed at time:{1}", e.Name,
DateTime.Now.ToLocalTime());
Thread.Sleep(1000);
if (GetAccessLoop(pathtomonitor + "\\" + e.Name))
{
parsefile(pathtomonitor + "\\" + e.Name);
Console.WriteLine("worked");
}
else
{
//writetologs("Was not able to get access to" + e.Name);
Console.WriteLine("didnt work");
}
_lastTimeFileWatcherEventRaised = DateTime.Now;
}
}
**问题:**只有一个文件被存储在字符串中,而不是两个。我希望所有添加到文件夹的文件都被存储,这样我就可以一次从列表中提取一个文件,并在完成编码后删除它们。
如何存储文件系统观察器检测到的所有文件,以便我可以保存同时放入的文件?
我会使用内存流吗?????
在事件处理程序中休眠是个坏主意。事件处理程序应该尽可能快。您希望事件处理程序记下新文件(例如,通过将文件名或路径添加到线程安全集合(如 ConcurrentQueue))然后退出。然后,您需要一个单独的任务来根据程序的需要处理该集合中的条目。
这是一个简化的例子:
async Task Main()
{
var pathtomonitor = @"C:\Temp\FileWatcherExample";
System.IO.Directory.CreateDirectory(pathtomonitor);
FileSystemWatcher watcher = new FileSystemWatcher(pathtomonitor);
watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.FileName;
watcher.EnableRaisingEvents = true;
watcher.IncludeSubdirectories = false;
//add event handlers
watcher.Created += watcher_Created;
// As programmed, this will await forever since there
// isn't a mechanism to end ProcessNewFiles()
await ProcessNewFiles();
}
ConcurrentQueue<string> createdFiles = new ConcurrentQueue<string>();
private async Task ProcessNewFiles()
{
while (true) // In production code we'd use a cancellation token to exit
{
while (createdFiles.TryDequeue(out var path))
{
Console.WriteLine($"Processing {path}");
}
// This is more efficienty handled with Channels, but we'll
// introduce a small delay here to keep the code example
// simple
await Task.Delay(100);
}
}
private void watcher_Created(object sender, FileSystemEventArgs e)
{
if (e.ChangeType == WatcherChangeTypes.Created)
{
Console.WriteLine($"New file: {e.FullPath}");
createdFiles.Enqueue(e.FullPath);
}
}
我很喜欢另一个答案中的建议,即在处理完文件后将其移动到“存档”文件夹中。
您似乎每 2000 秒轮询一次新文件,却无法查看那里有什么以及新文件是什么?您需要将旧文件保存在交付它们的同一文件夹中吗?
你能创建一个“归档”子文件夹并将处理过的文件移到那里吗?这样您就知道当前文件夹(交付文件夹)中的任何文件仍需要处理。此外,如果过程的任何部分失败,您永远不会将文件移动到存档。
此外,听起来您没有存储添加的文件列表,而只存储了一个?我们可以看看您是如何访问新文件列表的吗?