Cześć , problem pewnie stary bo trochę przejrzałem ale u mnie pomimo wdrożenia jakiś sugestii nie działa to tak jak bym chciał . Link całości programu na githubie .
https://github.com/KovalFunky/DirectoryCrawler
Jest klasa która agreguje wszystkie pliki we wskazanym katalogu i podkatalogach . Klasa może pracować jedno lub wielowątkowo w zależności od wybranego trybu i generuje zdarzenie informujące o dodaniu plików do listy .
Jeżeli testuję działanie w aplikacji konsolowej wszystko działa bez zarzutu , w obydwu trybach ..
W przypadku spięcia tego z WF zaczynają się schody . W trybie jednowątkowym aplikacja działa ale nie pokazuje postępu działania enumeratora na bieżąco tylko dopiero jak skończy.
W trybie wielowątkowym po prostu zawisa na zawsze .
Wszystkie opisane klasy poniżej . Ktoś coś gdzieś naprowadzi ...
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EnumerateAllFiles
{
public class EnumerateAllFilesClass
{
private ConcurrentBag<FileInfo> allFileList = new ConcurrentBag<FileInfo>();
private ConcurrentBag<DirectoryInfo> allDirectories = new ConcurrentBag<DirectoryInfo>();
private ConcurrentBag<DirectoryInfo> blockDirectories = new ConcurrentBag<DirectoryInfo>();
private readonly bool _multi;
private EventManagerLibraryClass EventManager=new EventManagerLibraryClass();
public event EventHandler<OwnArgsLibraryClass> ReportStatus;
public event EventHandler<OwnArgsLibraryClass> EndOfProgress;
public EnumerateAllFilesClass(bool multi=true) // konstruktor - multithreading ON - OFF
{
_multi = multi;
}
public void Initialize(DirectoryInfo directory) // procedura startowa dla całego procesu enumeracji
{
var data = FirstPass(directory);
AddFilesToList(data.GrabFiles);
CrawlingDirectories(data.GrabDirectories);
EventManager.FireEvent(EndOfProgress);
}
private void CrawlingDirectories(IEnumerable<DirectoryInfo> grabDirectories) // główna procedura rekurencyjna - główna pętla
{
if (_multi)
{
Parallel.ForEach(grabDirectories, directory =>
{
var data = FirstPass(directory);
AddFilesToList(data.GrabFiles);
CrawlingDirectories(data.GrabDirectories);
});
}
else
{
foreach (var directory in grabDirectories)
{
var data = FirstPass(directory);
AddFilesToList(data.GrabFiles);
CrawlingDirectories(data.GrabDirectories);
}
}
}
private (IEnumerable<FileInfo> GrabFiles, IEnumerable<DirectoryInfo> GrabDirectories) FirstPass(DirectoryInfo actualDirectory) // pobranie podkatalogów ze wskazanego katalogu
{
var ret = GrabFilesFromDirectory(actualDirectory);
var ret1 = GrabSubDirectories(actualDirectory);
return (GrabFiles: ret, GrabDirectories: ret1);
}
private void AddFilesToList(IEnumerable<FileInfo> grabFiles) // dodanie plików do listy końcowych wyników programu
{
foreach (FileInfo file in grabFiles)
{
allFileList.Add(file);
}
EventManager.FireEvent(ReportStatus, new OwnArgsLibraryClass()
{ allFilesCount = allFileList.Count, allDirectoryCount = allDirectories.Count, blockDirectoryCount = blockDirectories.Count });
}
private IEnumerable<FileInfo> GrabFilesFromDirectory(DirectoryInfo actualDirectory) // pobranie listy plików ze wskazanego katalogu
{
IEnumerable<string> col = null;
try
{
col = Directory.EnumerateFiles(actualDirectory.FullName);
}
catch (Exception err) // nie można pobrać plików z wskazanego katalogu
{
return new List<FileInfo>();
}
var newList = new List<FileInfo>();
foreach (var item in col)
{
try
{
newList.Add(new FileInfo(item));
}
catch (Exception)
{
throw;
}
}
return newList;
}
private IEnumerable<DirectoryInfo> GrabSubDirectories (DirectoryInfo actualDirectory) // pobranie listy podkatalogów ze wskazanej lokalizacji
{
IEnumerable<string> col = null;
try
{
col = Directory.EnumerateDirectories(actualDirectory.FullName);
allDirectories.Add(actualDirectory);
}
catch (Exception err) // nie można pobrać plików z wskazanego katalogu
{
blockDirectories.Add(actualDirectory); // dodanie zablokowanego katalogu do listy blokowanych
return new List<DirectoryInfo>();
}
var newList = new List<DirectoryInfo>();
foreach (var item in col)
{
try
{
newList.Add(new DirectoryInfo(item));
}
catch (Exception)
{
throw;
}
}
return newList;
}
}
}
kod consoli
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EnumerateAllFiles;
namespace ConsolaTestowa
{
internal class Program
{
static void Main(string[] args)
{
var eaf = new EnumerateAllFiles.EnumerateAllFilesClass();
eaf.ReportStatus += Eaf_ReportStatus;
eaf.EndOfProgress += Eaf_EndOfProgress;
eaf.Initialize(new System.IO.DirectoryInfo(@"C:\"));
}
private static void Eaf_EndOfProgress(object sender, OwnArgsLibraryClass e)
{
Console.WriteLine("KONIEC");Console.ReadKey();
}
private static void Eaf_ReportStatus(object sender, OwnArgsLibraryClass e)
{
Console.WriteLine(e.allFilesCount);
}
}
}
kod WF
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using EnumerateAllFiles;
using static System.Net.Mime.MediaTypeNames;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
EnumerateAllFilesClass ea;
if ((sender as Button).Name.Contains("Single"))
{
ea = new EnumerateAllFilesClass(false);
}
else
{
ea = new EnumerateAllFilesClass(true);
}
ea.ReportStatus += Ea_ReportStatus;
ea.EndOfProgress += Ea_EndOfProgress;
ea.Initialize(new System.IO.DirectoryInfo(@"C:\"));
}
private void Ea_EndOfProgress(object sender, OwnArgsLibraryClass e)
{
Update_Label(statusLabel2, "KONIEC");
}
private void Ea_ReportStatus(object sender, OwnArgsLibraryClass e)
{
var data = new StorageClass() { allFilesCount = e.allFilesCount };
Update_Label(statusLabel1, data.allFilesCount.ToString());
}
private void Update_Label (Label labelToUpdate , string textToUpdate)
{
if (labelToUpdate != null)
{
if (labelToUpdate.InvokeRequired)
{
Action safeWrite = delegate { labelToUpdate.Text = textToUpdate; };
labelToUpdate.Invoke(safeWrite);
}
labelToUpdate.Text = textToUpdate;
}
}
}
}
Wyzwalanie zdarzeń
using System;
namespace EnumerateAllFiles
{
public class EventManagerLibraryClass
{
internal void FireEvent(EventHandler<OwnArgsLibraryClass> MyEvent, OwnArgsLibraryClass ownArgs=null)
{
if (ownArgs == null) { ownArgs = new OwnArgsLibraryClass(); }
MyEvent?.Invoke(this, ownArgs);
}
}
}