一次放置多个文件时,如何创建一个队列来存储添加到文件夹的传入文件?

问题描述 投票:0回答:2

我做了一个服务来监视文件夹以查看何时添加新文件。当添加新文件时,将文件按行分解(每行存储在一个列表中),然后将每行存储的数据编码成二维码图像。 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;
    }
}

**问题:**只有一个文件被存储在字符串中,而不是两个。我希望所有添加到文件夹的文件都被存储,这样我就可以一次从列表中提取一个文件,并在完成编码后删除它们。

如何存储文件系统观察器检测到的所有文件,以便我可以保存同时放入的文件?

我会使用内存流吗?????

c# list file memory filesystemwatcher
2个回答
0
投票

在事件处理程序中休眠是个坏主意。事件处理程序应该尽可能快。您希望事件处理程序记下新文件(例如,通过将文件名或路径添加到线程安全集合(如 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);
    }
}

我很喜欢另一个答案中的建议,即在处理完文件后将其移动到“存档”文件夹中。


0
投票

您似乎每 2000 秒轮询一次新文件,却无法查看那里有什么以及新文件是什么?您需要将旧文件保存在交付它们的同一文件夹中吗?

你能创建一个“归档”子文件夹并将处理过的文件移到那里吗?这样您就知道当前文件夹(交付文件夹)中的任何文件仍需要处理。此外,如果过程的任何部分失败,您永远不会将文件移动到存档。

此外,听起来您没有存储添加的文件列表,而只存储了一个?我们可以看看您是如何访问新文件列表的吗?

© www.soinside.com 2019 - 2024. All rights reserved.