簡體   English   中英

.NET C# 中的 FileSystemWatcher 有什么替代方案嗎?

[英]Is there any alternative for FileSystemWatcher in .NET C#?

我是 .NET Core 的新手,目前正在研究一個需要處理目錄中文件的用例。

應用程序使用FileSystemWatcher類來監視目錄。
下面是我用來監視目錄的代碼。


private FileSystemWatcher watcher = new FileSystemWatcher();
private List<CustomFileEvent> custEventsList = new List();

private void MonitorDirectory(strinig dirName) 
{
    
    watcher.Path = dirName;
    watcher.IncludeSubdirectories = true;
    
    watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.CreationTime | NotifyFilters.LastAccess | NotifyFilters.DirectoryName;
    
    watcher.Filter = "*.*";
    
    // Add created event handler
    watcher.Created += new FileSystemEventHandler(OnChanged);
    //
    //watcher.Deleted += new FileSystemEventHandler(OnChanged);
    watcher.Renamed += new RenamedEventHandler(OnRenamed);

    // Setting the internal buffer size to 24kb. By default it is 8kb
    watcher.InternalBufferSize = 24000;

    // Begin watching.
    watcher.EnableRaisingEvents = true;
    
    watcher.WaitForChanged(WatcherChangeTypes.All);
}

private void OnChanged(object source, FileSystemEventArgs e)
{
    Console.WriteLine("Event Occured");
    Console.WriteLine($"File: {e.FullPath} {e.ChangeType}");
    
    // Code to handle the file created event
    // Passing the parameters fileName, fullPath, dateTime, and size of the file
    CreateFileEvent(......)
    
}

private void CreateFileEvent(string fileName, string fullPath, DateTime timeStamp,long size) {
    // Code to create the File created event
    var customFileEvent = new CustomFileEvent()
    {
        FileName = fileName,
        FullPath = fullPath,
        TimeStamp = timeStamp,
        Size = size
    };
    
    custEventsList.Add(customFileEvent);
}

private void TimerFunction(object sender, ElapsedEventArgs e)
{
    if (custEventsList != null && custEventsList.Count != 0)
    {
        Console.WriteLine("Total events :: " + custEventsList .Count);

        foreach (var evnt in custEventsList)
        {
            ProcessEvent( ..... arguments to send the file watcher events);
        }
    }
    
    // Clear your file List.
    custEventsList = new List<CustomFileEvent>();  // CustomFileEvent is a custom class
}

假設應用程序正在監視文件夾 C:\\MyAppFiles\\AppEvents
創建 TimerFunction 以處理每 20 秒間隔后的事件。 ProcessEvent方法實際上用於將文件詳細信息發送到另一個處理文件並刪除它的 Windows 服務。

使用此代碼,我可以成功地一次處理一個文件並將其刪除。 當我嘗試使用以下步驟處理多個文件時會出現問題。

  1. 將 FileData.txt 復制到監視文件夾。 Created事件發生並調用 OnChanged 函數。
  2. CreateFileEvent創建自定義事件。
  3. TimerFunction 每 20 秒處理一次事件。
  4. 在 20 秒之前復制 FileData_2.txt。
  5. 該文件夾有 2 個文件需要處理。
  6. 該代碼處理文件並刪除文件。 該文件夾現在是空的。
  7. 現在我放置了另一個文件 FileData_3.txt
  8. 發現未生成Created事件。 並且文件沒有得到處理。

更新:我觀察到在 ProcessEvent 函數中處理文件后, FileSystemWatcher 被自動處理。 僅當我嘗試放置多個文件進行處理時才會發生這種情況。 在單個文件的情況下,它可以成功運行。

請指教。

我不知道這是否是一個完整的解決方案,但是您對這段代碼有一個大問題:

  • 您的 FileSystemWatcher 變量在 foreach 循環中的每次迭代后都會被銷毀。

這是一個問題,因為您不知道該對象是否仍在某處被引用。 您創建的所有 FileSystemWatcher 都應該保存在一個數組或類似的東西中,在調用您的方法后不會被銷毀(即作為實例變量)。

由於您沒有顯示實際處理事件的代碼,因此很難准確判斷問題出在哪里。 但請記住,如果您的線程卡在 OnChanged 方法中,則在您正確離開該方法之前不會觸發其他事件。

請分享方法CreateFileEventTimerFunction的代碼。

編輯:

您可能需要查看ConcurrentQueue .Net 類,因為您有多個線程在操作列表,並且不注意線程安全。

此外,您不必調用 WaitForChanged 和方法結束,將 EnableRaisingEvent 設置為 true 就足夠了。

最后我能夠解決這個問題。 使用ManualResetEvent manualResetEvent = new ManualResetEvent(false); 作為成員變量和manualResetEvent.WaitOne(); 進入函數。

下面是代碼

private FileSystemWatcher watcher = new FileSystemWatcher();
private List<CustomFileEvent> custEventsList = new List();

private readonly ManualResetEvent manualResetEvent = new ManualResetEvent(false);

private void MonitorDirectory(strinig dirName) 
{
    
    watcher.Path = dirName;
    watcher.IncludeSubdirectories = true;
    
    watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.CreationTime | NotifyFilters.LastAccess | NotifyFilters.DirectoryName;
    
    watcher.Filter = "*.*";
    
    // Add created event handler
    watcher.Created += new FileSystemEventHandler(OnChanged);
    //
    //watcher.Deleted += new FileSystemEventHandler(OnChanged);
    watcher.Renamed += new RenamedEventHandler(OnRenamed);

    // Setting the internal buffer size to 24kb. By default it is 8kb
    watcher.InternalBufferSize = 24000;

    // Begin watching.
    watcher.EnableRaisingEvents = true;
    
    // watcher.WaitForChanged(WatcherChangeTypes.All);
    manualResetEvent.WaitOne();
}

希望這對面臨同樣問題的其他人有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM