在Try Catch中捕获错误后,我如何返回循环并继续搜索C驱动器?

本文关键字:循环 返回 继续 驱动器 搜索 何返回 Catch Try 错误 | 更新日期: 2023-09-27 18:02:38

我正在使用Directory搜索C驱动器中的MP3文件。GetFiles(所有目录),但当涉及到搜索回收站我得到和访问错误。我用Try Catch来抓它。我想知道的是如何忽略错误并继续搜索驱动器。这是我的代码…

    private void toolStripButtonSearch_Click(object sender, EventArgs e)
    {
        DialogResult result = folderBrowserDialogMain.ShowDialog();
        if(result == DialogResult.OK)
        {
            try
            {
                foreach (String file in Directory.GetFiles(folderBrowserDialogMain.SelectedPath, "*.mp3", SearchOption.AllDirectories))
                {
                    FileInfo fi = new FileInfo(file);
                    ListViewItem lvi = new ListViewItem(fi.Name);
                    listViewMain.Items.Add(lvi);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }

在Try Catch中捕获错误后,我如何返回循环并继续搜索C驱动器?

可以这样做:

IEnumerable<string> GetAllFiles(string path, string pattern)
{
    IEnumerable<string> files = null;
    try
    {
        files = Directory.GetFiles(path, pattern);
    }
    catch (UnauthorizedAccessException) { }
    if (files == null) yield break;
    foreach (var fname in files) yield return fname;
    foreach (var dname in Directory.GetDirectories(path))
    {
        foreach (var fname in GetAllFiles(dname, pattern)) yield return fname;
    }
}

并将其调用为

var allMP3s = GetAllFiles(@"c:'", "*.mp3" ).ToList();

一种捕获枚举驱动器中保持对目录内容进行延迟评估的能力的文件夹的错误的方法是触发事件,然后枚举这些事件。这避免了在try和catch块中使用yield返回块的问题。

请参见示例方法。

public class DirectoryEnumerator
{
    public class FileEventArgs : EventArgs
    {
        public FileInfo FileInfo { get; }
        public FileEventArgs(FileInfo fileInfo)
        {
            FileInfo = fileInfo;
        }
    }
    public class DirectoryEventArgs : EventArgs
    {
        public DirectoryInfo DirectoryInfo { get; }
        public DirectoryEventArgs(DirectoryInfo directoryInfo)
        {
            DirectoryInfo = directoryInfo;
        }
    }
    public class EventEnumerator<T> : IEnumerable<T>, IEnumerator<T>
    {
        private readonly Queue<T> _queue = new Queue<T>();
        private readonly ManualResetEvent _event;
        public bool Started { get; set; }
        public EventEnumerator()
        {
            _event = new ManualResetEvent(false);
        }
        public void Action(Action action)
        {
            Task.Run(() => action.Invoke()).ContinueWith(task => { MarkComplete(); });
        }
        public void Callback(T value)
        {
            Started = true;
            lock (_queue)
            {
                _queue.Enqueue(value);
                _event.Set();
            }
        }
        public void MarkComplete()
        {
            Started = false;
            _event.Set();
        }
        public void Dispose()
        {
        }
        public bool MoveNext()
        {
            _event.WaitOne();
            var notComplete = IsNotComplete();
            if (notComplete)
            {
                lock (_queue)
                {
                    Current = _queue.Dequeue();
                    if (_queue.Count == 0)
                        _event.Reset();
                }
            }
            return IsNotComplete();
        }
        private bool IsNotComplete()
        {
            return _queue.Count > 0 || Started;
        }
        public void Reset()
        {
            lock (_queue)
            {
                _queue.Clear();
            }
        }
        public T Current { get; private set; }
        object IEnumerator.Current
        {
            get { return Current; }
        }
        public IEnumerator<T> GetEnumerator()
        {
            while (this.MoveNext())
            {
                if (Current != null)
                {
                    yield return this.Current;
                }
            }
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    public DirectoryEnumerator()
    {
    }
    public event EventHandler OnNewFile;
    private void ProcessFile(FileInfo path)
    {
        OnNewFile?.Invoke(this, new FileEventArgs(path));
    }
    public event EventHandler OnNewDirectory;
    private void ProcessDirectory(DirectoryInfo path)
    {
        OnNewDirectory?.Invoke(this, new DirectoryEventArgs(path));
    }
    public static IEnumerable<FileInfo> GetFiles(DirectoryInfo directoryInfo, bool recurse = true)
    {
        var directoryEnumerator = new DirectoryEnumerator();
        var eventEnumeratingEnumerable = new EventEnumerator<FileInfo>();
        eventEnumeratingEnumerable.Action(() => { directoryEnumerator.Enumerate(directoryInfo, recurse); });
        directoryEnumerator.OnNewFile +=
            (sender, eventHandler) =>
            {
                eventEnumeratingEnumerable.Callback(((FileEventArgs)eventHandler).FileInfo);
            };
        return eventEnumeratingEnumerable;
    }
    public static IEnumerable<DirectoryInfo> GetDirectories(DirectoryInfo directoryInfo, bool recurse = true)
    {
        var directoryEnumerator = new DirectoryEnumerator();
        var eventEnumeratingEnumerable = new EventEnumerator<DirectoryInfo>();
        eventEnumeratingEnumerable.Action(() => { directoryEnumerator.Enumerate(directoryInfo, recurse); });
        directoryEnumerator.OnNewDirectory +=
            (sender, eventHandler) =>
            {
                eventEnumeratingEnumerable.Callback(((DirectoryEventArgs) eventHandler).DirectoryInfo);
            };
        return eventEnumeratingEnumerable;
    }

    public void Enumerate(DirectoryInfo directoryInfo, bool recurse = true)
    {
        Enumerate(directoryInfo, recurse, ProcessFile, ProcessDirectory);
    }
    private void Enumerate(DirectoryInfo directoryInfo, bool recurse, Action<FileInfo> fileAction, Action<DirectoryInfo> directoryAction)
    {
        TryEnumerateFiles(directoryInfo, fileAction);
        TryEnumerateDirectories(directoryInfo, recurse, fileAction, directoryAction);
    }
    private void TryEnumerateDirectories(DirectoryInfo directoryInfo, bool recurse, Action<FileInfo> fileAction, Action<DirectoryInfo> directoryAction)
    {
        try
        {
            foreach (var subDir in directoryInfo.GetDirectories("*.*", SearchOption.TopDirectoryOnly))
            {
                if (directoryAction != null)
                {
                    directoryAction(subDir);
                }
                if (recurse)
                {
                    Enumerate(subDir, true, fileAction, directoryAction);
                }
            }
        }
        catch (Exception ex)
        {
            Logger.Debug($"Failed to enumerate subdirectories within directory {directoryInfo.FullName}", ex);
        }
    }
    private void TryEnumerateFiles(DirectoryInfo directoryInfo, Action<FileInfo> fileAction)
    {
        try
        {
            foreach (var file in directoryInfo.GetFiles("*.*", SearchOption.TopDirectoryOnly))
            {
                if (fileAction != null)
                {
                    fileAction(file);
                }
            }
        }
        catch (Exception ex)
        {
            Logger.Debug($"Failed to enumerate files within directory {directoryInfo.FullName}", ex);
        }
    }
    private static void Examples()
    {
        // Recursive file enumeration
        var files1 = DirectoryEnumerator.GetFiles(new DirectoryInfo("C:''")).ToList();
        // File enumeration
        var files2 = DirectoryEnumerator.GetFiles(new DirectoryInfo("C:''"), false).ToList();
        // Recursive directory enumeration
        var directory1 = DirectoryEnumerator.GetDirectories(new DirectoryInfo("C:''")).ToList();
        // Directory enumeration
        var directory2 = DirectoryEnumerator.GetDirectories(new DirectoryInfo("C:''"), false).ToList();

        // Event enumeration
        var directoryEnumerator = new DirectoryEnumerator();
        directoryEnumerator.OnNewFile += (sender, file) => {
            // dosomething 
        };
        directoryEnumerator.OnNewDirectory += (sender, file) => {
            // dosomething 
        };
        directoryEnumerator.Enumerate(new DirectoryInfo("C:''"), false);
    }
}