Implementazione BackGroundWorker in un Custom Control...

giovedì 16 luglio 2009 - 16.54

Revan1985 Profilo | Junior Member

Ho un piccolo problema...
Ho creato un mio controllo custom per la gestione di un filesystem...
Mi serve sapere come posso, dato il controllo, implementarci dentro un background worker, visto che i tempi di attesa per molti file sono impossibili...
Qui il codice :

using System; using System.IO; using System.Windows.Forms; using System.ComponentModel; using System.Collections.Generic; namespace ImpronteCS { class FileSystemTreeView : TreeView { public List<string> FileList; public bool SubFolders = false; public string Format = string.Empty; public int FileCount = 0; public FileSystemTreeView() { this.BeforeExpand += new TreeViewCancelEventHandler(FS_BeforeExpand); this.AfterCollapse += new TreeViewEventHandler(FS_AfterCollapse); } private void FS_AfterCollapse(object sender, TreeViewEventArgs e) { e.Node.Nodes.Clear(); e.Node.Nodes.Add("."); } private void FS_BeforeExpand(object sender, TreeViewCancelEventArgs e) { try { e.Node.Nodes.Clear(); string needle = e.Node.Tag as string; string[] folders = Directory.GetDirectories(needle); string[] files = Directory.GetFiles(needle); if (SubFolders) { foreach (string folder in folders) { try { string[] s_folders = Directory.GetDirectories(folder); string[] s_files = Directory.GetFiles(folder); TreeNode t_folder = getNode(folder); foreach (string s_folder in s_folders) t_folder.Nodes.Add(getNode(s_folder)); foreach (string s_file in s_files) if (s_file.EndsWith(Format)) { FileList.Add(s_file); t_folder.Nodes.Add(getNode(s_file)); } e.Node.Nodes.Add(t_folder); } catch (IOException ioe) { } catch (UnauthorizedAccessException uae) { } finally { } } } foreach (string file in files) { if (file.EndsWith(Format)) { FileList.Add(file); e.Node.Nodes.Add(getNode(file)); } } } catch (IOException ioe) { } catch (UnauthorizedAccessException uae) { } finally { } } public void Load(string needle) { if (FileList == null) FileList = new List<string>(); FileList.Clear(); this.Nodes.Clear(); TreeNode n_node = getNode(needle); n_node.Nodes.Add("."); this.Nodes.Add(n_node); this.Nodes[0].Expand(); FileCount = 0; FileSystemCounter.Count(needle, Format, SubFolders, ref FileCount); } private TreeNode getNode(string path) { TreeNode r_node = new TreeNode(); int limit = path.LastIndexOf('\\') + 1; string name = path.Substring(limit, (path.Length - limit)); if (name.Length < 1) name = path.Substring(0, path.Length - 1); r_node.Text = name; r_node.Tag = path; return r_node; } } }

using System; using System.IO; namespace ImpronteCS { public class FileSystemCounter { public static void Count(string path, string file_type, bool sub_folders, ref int count) { foreach (string file in Directory.GetFiles(path)) { try { if(file.EndsWith(file_type)) count++; } catch (IOException ioe) { } catch (UnauthorizedAccessException uae) { } finally { } } if (sub_folders) foreach (string folder in Directory.GetDirectories(path)) { try { Count(folder, file_type, sub_folders, ref count); } catch (IOException ioe) { } catch (UnauthorizedAccessException uae) { } finally { } } } } }

il primo carica i file del filesystem, la seconda li conta...
come faccio a mettere il tutto in un background worker?

grazie a tutti

Non c'è emozione; c'è pace.
Non c'è ignoranza; c'è conoscenza.
Non c'è inquietudine; c'è serenità.
Non c'è caos; c'è armonia.
Non c'è morte; c'è la Forza.

Jeremy Profilo | Guru

Ciao Davide
>come faccio a mettere il tutto in un background worker?
Non capisco il senso della domanda ..... intendi:
Come fare a dichiarare un BackGroundWorker e poi sai già tu tutto il resto?
o
Come fare a dichiarare un BackGroundWorker e tutto il resto?

Facci sapere.....
Ciao

Revan1985 Profilo | Junior Member

so già come implementare un bgw, ma non so come incapsularlo lì dentro...
se provo a fare un runAsync leggendo i files, mi dice che è già in uso...

Non c'è emozione; c'è pace.
Non c'è ignoranza; c'è conoscenza.
Non c'è inquietudine; c'è serenità.
Non c'è caos; c'è armonia.
Non c'è morte; c'è la Forza.

Jeremy Profilo | Guru

Ciao Davide.
L'errore che ricevi, dipende dal fatto che, probabilmente, tenti di accedere al file con due thread contemporaneamente.
Se posti il codice che ti genera l'errore (quello già in Multithreading), vediamo di dargli un occhio.

Facci sapere...
Ciao

Revan1985 Profilo | Junior Member

Sono riuscito a fare quello ce volevo...
solo che vorrei una prograssione dci file contati ogni tot secondi...

questo il codice implenmentato...

Albero

using System; using System.IO; using System.Windows.Forms; using System.ComponentModel; using System.Collections.Generic; namespace ImpronteCS { class FileSystemTreeView : TreeView { /// <summary>Lista dei files caricati</summary> public List<string> FileList; /// <summary>Aggiungere le sottodirectory?</summary> public bool SubFolders = false; /// <summary>Il formato dei files da caricare</summary> public string Format = string.Empty; /// <summary>Conteggio dei file [si può omettere]</summary> public int FileCount { get { return (FileList != null) ? FileList.Count : -1; } } /// <summary>Costruttore</summary> public FileSystemTreeView() { this.BeforeExpand += new TreeViewCancelEventHandler(FS_BeforeExpand); this.AfterCollapse += new TreeViewEventHandler(FS_AfterCollapse); loader.WorkerReportsProgress = true; loader.WorkerSupportsCancellation = true; loader.DoWork += new DoWorkEventHandler(this.Work); loader.ProgressChanged += new ProgressChangedEventHandler(this.Progress); loader.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.Completed); } private void FS_AfterCollapse(object sender, TreeViewEventArgs e) { //Pulisci i nodi. for (int i = 0; i < e.Node.Nodes.Count; ++i) { foreach (string file in FileList) { if (file.EndsWith(e.Node.Nodes[i].Text)) { FileList.Remove(file); break; } } } e.Node.Nodes.Clear(); e.Node.Nodes.Add("."); Count(this, new SystemTreeArgs(FileList.Count)); } private void FS_BeforeExpand(object sender, TreeViewCancelEventArgs e) { try { e.Node.Nodes.Clear(); string needle = e.Node.Tag as string; string[] folders = Directory.GetDirectories(needle); string[] files = Directory.GetFiles(needle); //Carico le sottodirectory? if (SubFolders) { foreach (string folder in folders) { try { string[] s_folders = Directory.GetDirectories(folder); string[] s_files = Directory.GetFiles(folder); TreeNode t_folder = getNode(folder); foreach (string s_folder in s_folders) t_folder.Nodes.Add(getNode(s_folder)); foreach (string s_file in s_files) { //E' il formato che voglio? if (s_file.EndsWith(Format)) { //Allora aggiungilo. //if(!FileList.Contains(s_file)) //FileList.Add(s_file); t_folder.Nodes.Add(getNode(s_file)); } } e.Node.Nodes.Add(t_folder); } catch (IOException ioe) { //Fai niente } catch (UnauthorizedAccessException uae) { //Fai niente } finally { //Fai niente } } } foreach (string file in files) { //E' il formato che voglio? if (file.EndsWith(Format)) { //Allora aggiungilo. if (!FileList.Contains(file)) FileList.Add(file); e.Node.Nodes.Add(getNode(file)); } } } catch (IOException ioe) { //Fai niente } catch (UnauthorizedAccessException uae) { //Fai niente } finally { //Fai niente } Count(this, new SystemTreeArgs(FileList.Count)); } /// <summary>Carica la struttura</summary> /// <param name="needle">Path da cui partire</param> public void Load(string needle) { //loader.RunWorkerAsync(new object[] { needle, Format, SubFolders}); if (FileList == null) FileList = new List<string>(); //Cancella la lista dei files. FileList.Clear(); //Cancella i nodi this.Nodes.Clear(); //prendi il nodo principale. TreeNode n_node = getNode(needle); n_node.Nodes.Add("."); this.Nodes.Add(n_node); //Espando il nodo root. this.Nodes[0].Expand(); Count(this, new SystemTreeArgs(FileList.Count)); if (!loader.IsBusy) { loader.RunWorkerAsync(new object[] { needle, Format, SubFolders }); } else { loader.CancelAsync(); } } /// <summary>Crea il nodo dell'albero</summary> /// <param name="path">La cartella del Nodo.</param> /// <returns>TreeNode</returns> private TreeNode getNode(string path) { TreeNode r_node = new TreeNode(); int limit = path.LastIndexOf('\\') + 1; string name = path.Substring(limit, (path.Length - limit)); if (name.Length < 1) name = path.Substring(0, path.Length - 1); r_node.Text = name; r_node.Tag = path; return r_node; } BackgroundWorker loader = new BackgroundWorker(); private void Work(object sender, DoWorkEventArgs e) { //Conteggia i files [si può omettere] object[] data = e.Argument as object[]; int Cnt = 0; FileSystemCounter.Count(data[0] as string, data[1] as string, (bool)data[2], ref Cnt); e.Result = Cnt; } private void Progress(object sender, ProgressChangedEventArgs e) { } private void Completed(object sender, RunWorkerCompletedEventArgs e) { if ((!e.Cancelled) && (e.Error == null)) TotalCount(this.TotalCount, new SystemTreeArgs((Convert.ToInt32(e.Result)))); else TotalCount(this.TotalCount, new SystemTreeArgs(0)); } public delegate void CountChanged(object sender, SystemTreeArgs e); public event CountChanged Count; public delegate void TotalCountChanged(object sender, SystemTreeArgs e); public event TotalCountChanged TotalCount; } public class SystemTreeArgs : EventArgs { private int count; public SystemTreeArgs(int count) { this.count = count; } public int Count { get { return count; } } } }

using System; using System.IO; namespace ImpronteCS { public class FileSystemCounter { public static void Count(string path, string file_type, bool sub_folders, ref int count) { foreach (string file in Directory.GetFiles(path)) { try { if(file.EndsWith(file_type)) count++; } catch (IOException ioe) { } catch (UnauthorizedAccessException uae) { } finally { } } if (sub_folders) foreach (string folder in Directory.GetDirectories(path)) { try { Count(folder, file_type, sub_folders, ref count); } catch (IOException ioe) { } catch (UnauthorizedAccessException uae) { } finally { } } } } }

ora, vorrei che ogni tot secondi, la mia bellissima classe di conteggio file [che con 50000+ file ci mettono ben 1 minuto], mandassero al bgw un bel messaggino "Ho processato X files"...
come faccio?

Non c'è emozione; c'è pace.
Non c'è ignoranza; c'è conoscenza.
Non c'è inquietudine; c'è serenità.
Non c'è caos; c'è armonia.
Non c'è morte; c'è la Forza.

Jeremy Profilo | Guru

Ciao.
Nella gestione dell'evento DoWork, puoi utilizzare il metodo ReportProgress del BackGroundWorker per impostare un valore intero da recuperare nella gestione dell'evento ProgressChanged asttraverso la classe ProgressChangedEventArgs.

Facci sapere....
Ciao

Revan1985 Profilo | Junior Member

questo lo so, ma visto che io faccio un uso ricorsivo del metodo count della classe di conteggio, come faccio?
ci associo un evento?

Non c'è emozione; c'è pace.
Non c'è ignoranza; c'è conoscenza.
Non c'è inquietudine; c'è serenità.
Non c'è caos; c'è armonia.
Non c'è morte; c'è la Forza.

Jeremy Profilo | Guru

Ciao Davide.
In questo caso le cose cambiano un pochino....nel senso che io, avrei fatto ereditare la mia classe da BackGroundWorker ..... ad ogni modo, per come è la situazione in questo momento ..... SI, devi scatenare un'evento nella tua classe nella quale gestione chiamerai il metodo ReportProgress per impostare il valore della percentuale di completamento.

Facci sapere....
Ciao

Revan1985 Profilo | Junior Member

hai un tutorial che spiega come ereditare un backgroundworker, o come va impostata la classe quando eredita?

Non c'è emozione; c'è pace.
Non c'è ignoranza; c'è conoscenza.
Non c'è inquietudine; c'è serenità.
Non c'è caos; c'è armonia.
Non c'è morte; c'è la Forza.
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5