How to make foreac loop faster ?

Sani Berko 41 Reputation points
2022-08-15T09:55:45.837+00:00
                    dic = new Dictionary<string, long>();  
  
                    var filesl = GetFiles(@"D:\", "*.*").ToList();  
                    foreach (var item in filesl)  
                    {  
                        FileInfo info = new FileInfo(item);  
                        if (File.Exists(info.FullName))  
                        {  
                            dic.Add(item, info.Length);  
                        }  
                    }  

I'm using wpf and c#

the foreach loop takes a lot of time. i thought to use backgroundworker or something else that will make the foreach async maybe.

i want to give the user some notice on label maybe that it's getting files like "getting files progress". the problem is that when it's doing the foreach loop the whole application freeze until the foreach loop end.

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,289 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
7,606 questions
XAML
XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
604 questions
No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Castorix31 69,176 Reputation points
    2022-08-15T10:03:18.14+00:00

    the problem is that when it's doing the foreach loop the whole application freeze until the foreach loop end.

    As you said, you can use a BackgroundWorker or a Thread


  2. Karen Payne MVP 30,366 Reputation points
    2022-08-15T11:06:41.797+00:00

    I would simply show progress by file name in a label using code as per below (written in .NET Core). The only thing I did not include was code to cancel which can be done with a CancellationToken

    public class FileOperations  
    {  
        public delegate void OnTraverse(string sender);  
        public event OnTraverse Traverse;  
        public delegate void OnDone();  
        public event OnDone Done;  
      
        public async Task CollectFiles(string path, string searchPattern, SearchOption searchOption = SearchOption.TopDirectoryOnly)  
        {  
            using var enumerator = await Task.Run(() => Directory.EnumerateFiles(path, searchPattern, searchOption).GetEnumerator());  
            while (await Task.Run(() => enumerator.MoveNext()))  
            {  
                Traverse?.Invoke(enumerator.Current);  
            }  
      
            Done?.Invoke();  
        }  
    }  
    

    Form code

    using System;  
    using System.IO;  
    using System.Windows.Forms;  
    using IterateFoldersApp.Classes;  
      
    namespace IterateFoldersApp  
    {  
        public partial class Form1 : Form  
        {  
            public Form1()  
            {  
                InitializeComponent();  
            }  
      
            private async void button1_Click(object sender, EventArgs e)  
            {  
                FileOperations operations = new();  
                operations.Traverse += OperationsOnTraverse;  
                operations.Done += OnDone;  
                await operations.CollectFiles("TODO", "*.*", SearchOption.AllDirectories);  
            }  
      
            private void OnDone()  
            {  
                MessageBox.Show("Done");  
            }  
      
            private void OperationsOnTraverse(string sender)  
            {  
                FileInfo info = new (sender);  
                if (File.Exists(sender))  
                {  
                    label1.Text = $"Working {info.Name}";  
                }  
            }  
        }  
    }  
      
    

    Edit: If you want to figure out total files

    private static int FileCount(string directory)  
    {  
        DirectoryInfo dirInfo = new(directory);  
        return dirInfo.EnumerateDirectories()  
            .AsParallel()  
            .SelectMany(di => di.EnumerateFiles("*.*", SearchOption.AllDirectories))  
            .Count();  
    }  
    

    Then look at IProgress<int> and Report off IProgress.