簡體   English   中英

如何使用生產者/消費者隊列遞歸搜索文件夾和文件?

[英]How to do recursive search of Folders & Files using producer/consumer queues?

我想先搜索目錄,然后搜索其中的文件,搜索關鍵字。

我知道我需要兩個類,生產者 class 和消費者 class,但我不知道如何使用 c# 生產者/消費者隊列進行搜索?

public class Program
{
    private static void Main()
    {
        Queue<File> searchFile = new Queue<File>();
        Queue<Directory> searchDirectory = new Queue<Directory>();

        new Thread(searchDirectory).Start();

        for (int i = 0; i < 3; i++)
            new Thread(searchFile).Start();
    }
}

最初的問題:

  1. 您正在使用具有相同 scope 的相同變量名稱聲明 2 個不同類型的變量。
  2. 您不想在 Directory 上啟動線程搜索,而在 File 上啟動另一個搜索。

項目編號 2 的問題是您正在處理多線程的最大瓶頸之一 - 即磁盤 IO。 通過實現多個工作線程來執行磁盤 IO(在標准 HDD 設備上)將一無所獲。

詳細說明您要做什么(請舉例說明)。 可能會有更好的過程。

首先, Directory是一個 static class 所以你不能一個集合。 您將需要改用DirectoryInfo 其次,我將使用一個包含DirectoryInfo實例的隊列。 然后可以枚舉這些文件作為處理單個文件夾的一部分。

這是我使用生產者-消費者模式的方法。 此實現使用BlockingCollection class 作為阻塞隊列的實現。 阻塞隊列在生產者-消費者模式中非常有用,因為它們抽象了幾乎所有的生產者-消費者細節。

public class Searcher
{
  private BlockingCollection<DirectoryInfo> m_Queue = new BlockingCollection<DirectoryInfo>();

  public Searcher()
  {
    for (int i = 0; i < NUMBER_OF_THREADS; i++)
    {
      var thread = new Thread(Run);
      thread.IsBackground = true;
      thread.Start();
    }
  }

  public void Search(DirectoryInfo root)
  {
    m_Queue.Add(root);
  }

  private void Run()
  {
    while (true)
    {
      // Wait for an item to appear in the queue.
      DirectoryInfo root = m_Queue.Take();

      // Add each child directory to the queue. This is the recursive part.
      foreach (DirectoryInfo child in root.GetDirectories())
      {
        m_Queue.Add(child);
      }

      // Now we can enumerate each file in the directory.
      foreach (FileInfo child in root.GetFiles())
      {
        // Add your search logic here.
      }
    }
  }
}

我應該指出,大多數磁盤以更加序列化的方式工作,因此嘗試搜索文件的多個線程可能不會給你帶來很多好處,除非你的邏輯的 CPU 綁定部分很廣泛。

正如其他海報所暗示的那樣,嘗試執行 IO 的多個線程將導致問題。 但是,它們可以用於構建完整的目錄隊列(如果它非常深),然后是一個單獨的線程來在文件上執行正則表達式。 有點像這樣:

    class Program
{
    static void Main(string[] args)
    {
        ConcurrentQueue<DirectoryInfo> concurrentQueue = new ConcurrentQueue<DirectoryInfo>();
        GetAllDirectories(new DirectoryInfo(@"C:\local\oracle"), concurrentQueue);
        Action action = () =>{
            const string toFind = "ora";
            DirectoryInfo info;
            while(concurrentQueue.TryDequeue(out info))
            {
                FindInFile(toFind, info);
            }
        };

        Parallel.Invoke(action, action, action, action);
        Console.WriteLine("total found " + _counter);
        Console.ReadKey();
    }
    static int _counter = 0;
    static void FindInFile(string textToFind,DirectoryInfo dirInfo)
    {
        var files =dirInfo.GetFiles();
        foreach(FileInfo file in files)
        {
            using (StreamReader reader = new StreamReader(file.FullName))
            {
                string content = reader.ReadToEnd();

                Match match = Regex.Match(content, textToFind, RegexOptions.Multiline);

                if(match.Success)
                {
                    Interlocked.Increment(ref _counter);
                    Console.WriteLine(file.FullName + " found " + match.Captures.Count);

                    foreach(var t in match.Captures)
                    {
                        Console.WriteLine("-------------> char index" + match.Index);
                    }
                }
            }
        }
    }

    internal static void GetAllDirectories(DirectoryInfo root, ConcurrentQueue<DirectoryInfo> values)
    {
        foreach (var di in root.GetDirectories())
        {
            GetAllDirectories(di, values);
            values.Enqueue(di);
        }
    }
}

我已經編輯了這篇文章(正在等待同行評審)。 如果它確實獲得批准,我已經編輯了代碼以修復 scope 和拼寫錯誤的基本問題,但我認為您還沒有准備好使用多線程,更不用說生產者 - 消費者隊列(上帝知道我已經涉足多線程線程一段時間,我最終還是弄亂了我的實現,但那可能只是我。)。

您應該首先熟悉范圍和多線程。 特別是閱讀對實現成功的多線程解決方案至關重要的鎖定機制/並發問題。

其次,正如 IAbstract 建議的那樣,確實使用互斥體/信號量實現多個線程,以通過多線程獲得性能以及獲得所需的生產者-消費者隊列。

此外,如果您覺得舒服,您還可以查看最新的 Async CTP1 DataFlow 庫,該庫使用 Tasks Parallel Library 對該模式提供最新支持。 或者,您可以使用BlockingCollection來實現此模式。

Stackoverflow 也有一些圍繞你的問題的問題,並給出了一些很好的答案。 只需搜索“生產者-消費者”即可閱讀它們

暫無
暫無

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

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