Почему при поиске в файлах текста, когда есть много файлов для поиска, использование памяти превышает 2 ГБ? - PullRequest
0 голосов
/ 03 апреля 2019

Мне пришлось закрыть приложение из диспетчера задач.

Например, я ищу весь диск D: \, и там более 400000 файлов Первый раз он получает файлы, а второй раз ищет в каждом файле определенную строку.

Запуск фонового рабочего:

private void startButton_Click(object sender, EventArgs e)
        {
            ListViewCostumControl.lvnf.Items.Clear();
            numberoffiles = 0;
            numberofrestrictedFiles = 0;
            numberofdirs = 0;
            label24.Text = "0";
            label1.Text = "0";
            label15.Text = "0";
            Logger.Write("Operation started");
            label21.Text = "Phase 1: Retrieving files";
            label21.Visible = true;
            startButton.Enabled = false;
            stopButton.Enabled = true;
            pauseresumeButton.Enabled = true;
            label1.Select();
            timer1.Start();
            if (!backgroundWorker1.IsBusy)
            {
                SetWorkerMode(true);
                backgroundWorker1.RunWorkerAsync();
            }
        }

Внутри DoWork:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            _stopwatch.Restart();

            string[] values = textBox1.Text.Split(new string[] { ",," }, StringSplitOptions.None);
            DirSearch(textBox3.Text, textBox2.Text, values, worker, e);

            _stopwatch.Stop();
        }

Метод DirSearch:

int numberofdirs = 0;
        void DirSearch(string rootDirectory, string filesExtension, string[] textToSearch, BackgroundWorker worker, DoWorkEventArgs e)
        {
            List<string> resultsoftextfound = new List<string>();
            List<string> resultsoftextfound1 = new List<string>();
            List<string> filePathList = new List<string>();
            int numberoffiles = 0;
            try
            {
                filePathList = SearchAccessibleFilesNoDistinct(rootDirectory, null,worker,e).ToList();
            }
            catch (Exception err)
            {
                string ad = err.ToString();
            }
            label21.Invoke((MethodInvoker)delegate
                    {
                        label21.Text = "Phase 2: Searching in files";
                    });

            MyProgress myp = new MyProgress();
            myp.Report4 = filePathList.Count.ToString();
            foreach (string file in filePathList)
            {
                try
                {
                    var tempFR = File.ReadAllText(file);
                    _busy.WaitOne();
                    if (worker.CancellationPending == true)
                    {
                        e.Cancel = true;
                        return;
                    }

                    bool reportedFile = false;

                    for (int i = 0; i < textToSearch.Length; i++)
                    {
                        if (tempFR.IndexOf(textToSearch[i], StringComparison.InvariantCultureIgnoreCase) >= 0)
                        {
                            resultsoftextfound.Add(file + "  " + textToSearch[i]);
                            if (!reportedFile)
                            {
                                numberoffiles++;

                                myp.Report1 = file;
                                myp.Report2 = numberoffiles.ToString();
                                myp.Report3 = textToSearch[i];
                                backgroundWorker1.ReportProgress(0, myp);
                                reportedFile = true;
                            }
                        }
                    }
                    numberofdirs++;
                    label1.Invoke((MethodInvoker)delegate
                    {
                        label1.Text = string.Format("{0}/{1}", numberofdirs, myp.Report4);
                        label1.Visible = true;
                    });
                }
                catch (Exception)
                {

                }
            }
        }

И два метода рекурсивного поиска немного длинны, но все методы связаны друг с другом:

int counter = 0;
        IEnumerable<string> SearchAccessibleFilesNoDistinctOnlyExtension(string root, List<string> files)
        {
            if (files == null)
                files = new List<string>();
            if (Directory.Exists(root))
            {
                foreach (var file in Directory.EnumerateFiles(root))
                {
                    string extension = Path.GetExtension(file);
                    if (!files.Contains(extension))
                    {
                        files.Add(extension);
                        counter++;
                    }
                }

                foreach (var subDir in Directory.EnumerateDirectories(root))
                {
                    try
                    {
                        SearchAccessibleFilesNoDistinctOnlyExtension(subDir, files);
                    }
                    catch (UnauthorizedAccessException)
                    {

                    }
                }
            }
            return files;
        }

        string restrictedFile = "";
        List<string> restrictedFiles = new List<string>();
        int numberofrestrictedFiles = 0;
        int numberoffiles = 0;
        IEnumerable<string> SearchAccessibleFilesNoDistinct(string root, List<string> files,BackgroundWorker worker, DoWorkEventArgs e)
        {
            _busy.WaitOne();
            if (files == null)
                files = new List<string>();
            if (Directory.Exists(root))
            {
                foreach (var file in Directory.EnumerateFiles(root))
                {
                    if (worker.CancellationPending == true)
                    {
                        e.Cancel = true;
                        return files;
                    }
                    restrictedFile = file;
                    string ext = Path.GetExtension(file);
                    if (!files.Contains(file) && (ext == "." + textBox2.Text || textBox2.Text == "*"))
                    //if (!files.Contains(file) && ext == textBox2.Text)
                    {
                        files.Add(file);
                    }
                    numberoffiles++;
                    label24.Invoke((MethodInvoker)delegate
                    {
                        label24.Text = numberoffiles.ToString();
                        label24.Visible = true;
                    });
                }
                foreach (var subDir in Directory.EnumerateDirectories(root))
                {
                    if (worker.CancellationPending == true)
                    {
                        e.Cancel = true;
                        return files;
                    }
                    try
                    {
                        SearchAccessibleFilesNoDistinct(subDir, files,worker, e);
                        //files.Add(subDir);
                    }
                    catch (UnauthorizedAccessException)
                    {
                        restrictedFiles.Add(restrictedFile);
                        numberofrestrictedFiles++;
                        label11.Invoke((MethodInvoker)delegate
                        {
                            label11.Text = numberofrestrictedFiles.ToString();
                            label11.Visible = true;
                        });
                        continue;
                    }
                }
            }
            return files;
        }

Отлично работает с небольшим количеством файлов для поиска. Но я хочу иметь возможность искать и по большому количеству файлов. Например 400000 файлов. Проблема в том, что в какой-то момент все оперативное использование памяти 2 ГБ даже близко к 3 ГБ в некоторых точках.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...