Autor |
Beitrag |
Sh3va
Hält's aus hier
Beiträge: 6
|
Verfasst: Mo 09.01.12 14:31
Hallo zusammen,
ich bin noch neu in der Welt des Programmierens und vor allem ein Neuling in C#.
Habe (als Azubi) die Aufgabe bekommen ein Programm zu schreiben, dass die Ordnerstruktur (z.B.) eines Servers komplett durchgeht, Informationen speichert (ich wollte es mit einer XML-Datei versuchen) wie zum Beispiel den kompletten Pfad und die Ordnergröße (mit allen Daten/Ordner darunter).
Soweit habe ich es zum laufen bekommen, aber sobald die Ordnerstruktur umfassender wird, bleibt mein Programm stecken. Im Hintergrund läuft es weiter, dass sehe ich daran, dass in die XML-Datei weiterhin geschrieben wird, jedoch wird das Programm so gezeigt, als wenn es nicht mehr reagieren würde.
Habt ihr vllt. Tipps, wie ich mein Programm optimieren kann, oder andere Rangehensweisen an diese Problemstellung, womöglich mit einer anderen API oder Programmiersprache?
Anbei die Windows Form.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223:
| namespace MainProgram { public partial class Mainprogram : Form {
static int id = 0; static string pathXML; static string pathSuche;
public Mainprogram() { InitializeComponent(); }
// Durchlauf starten private void button1_Click(object sender, EventArgs e) { id = 0; // Zähler für die Anzahl der Ordner label1.Visible = true; label2.Visible = true; label2.Refresh(); TempList.Items.Clear(); XmlTextWriter textWriter = new XmlTextWriter(pathXML, null); DirectoryInfo target = new DirectoryInfo(pathSuche); textWriter.WriteStartDocument(); textWriter.WriteStartElement("Datenbank"); findeOrdner(target, textWriter); textWriter.WriteEndElement(); // Ends the document. textWriter.WriteEndDocument();
textWriter.Close(); }
// Rekursives durchgehen der Ordnerstruktur private void findeOrdner(DirectoryInfo d, XmlTextWriter textWriter) {
if (id == 0) { DirectoryInfo[] dis = { d }; foreach (DirectoryInfo di in dis) { try {
// Gruppe öffnen textWriter.WriteStartElement("Ordner ", id.ToString()); // Speicherort einfügen textWriter.WriteStartElement("Speicherort"); textWriter.WriteString(di.FullName); textWriter.WriteEndElement();
// Ordnername einfügen textWriter.WriteStartElement("Name"); textWriter.WriteString(di.ToString()); textWriter.WriteEndElement();
// Ordnergröße einfügen textWriter.WriteStartElement("Größe"); textWriter.WriteString(DirSize(di).ToString()); textWriter.WriteEndElement();
// Änderungsdatum einfügen textWriter.WriteStartElement("Datum"); textWriter.WriteString(di.LastWriteTime.ToString()); textWriter.WriteEndElement();
textWriter.WriteEndElement(); // close writer
id++;
listboxschreiben(di.FullName.ToString());
findeOrdner(di, textWriter); } catch (UnauthorizedAccessException) { continue; }
} } else { DirectoryInfo[] dis = d.GetDirectories();
foreach (DirectoryInfo di in dis) { try { if (string.Compare(di.ToString(), "~snapshot") != 0) { // Gruppe öffnen textWriter.WriteStartElement("Ordner ", id.ToString());
// Speicherort einfügen textWriter.WriteStartElement("Speicherort"); textWriter.WriteString(di.FullName); textWriter.WriteEndElement();
// Ordnername einfügen textWriter.WriteStartElement("Name"); textWriter.WriteString(di.ToString()); textWriter.WriteEndElement();
// Ordnergröße einfügen textWriter.WriteStartElement("Größe"); textWriter.WriteString(DirSize(di).ToString()); textWriter.WriteEndElement();
// Änderungsdatum einfügen textWriter.WriteStartElement("Datum"); textWriter.WriteString(di.LastWriteTime.ToString()); textWriter.WriteEndElement();
textWriter.WriteEndElement(); // close writer
id++;
listboxschreiben(di.FullName.ToString());
findeOrdner(di, textWriter); } } catch (UnauthorizedAccessException) { continue; }
} }
}
// Momentanen Ordner in Listbox schreiben public void listboxschreiben(string a) { label1.Text = id.ToString(); TempList.Items.Add(a); Thread.Sleep(1); TempList.Refresh(); label1.Refresh();
// Autoscroll der Listbox TempList.SelectedIndex = TempList.Items.Count - 1; TempList.SelectedIndex = -1;
}
// Ordnergröße ermitteln public long DirSize(DirectoryInfo d) { long Size = 0; // Add file sizes. FileInfo[] fis = d.GetFiles(); foreach (FileInfo fi in fis) { Size += fi.Length; } // Add subdirectory sizes. DirectoryInfo[] dis = d.GetDirectories(); foreach (DirectoryInfo di in dis) { try { Size += DirSize(di); } catch (UnauthorizedAccessException) { continue; } } return (Size); } // Speicherort der XML-Datei festlegen über Textbox1 private void button2_Click(object sender, EventArgs e) { if (textBox1.Text != "") { pathXML = textBox1.Text; button3.Visible = true; } }
// Startordner des Durchlaufs festlegen private void button3_Click(object sender, EventArgs e) { if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) { this.textBox2.Text = folderBrowserDialog1.SelectedPath; pathSuche = folderBrowserDialog1.SelectedPath; btnStart.Visible = true; } } } } |
Einloggen, um Attachments anzusehen!
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mo 09.01.12 14:51
Die ganze Ordnerfunktionalität steckt letztlich in der Windows API. Eine andere Programmiersprache zu wählen hilft also nicht da die API die gleiche bleibt. Mit der Geschwindigkeit wirst du also mehr oder weniger leben müssen.
Um die GUI sauberer zu gestalten solltest denn Vorgang des Ordners scannens in einen eigenen Thread(oder mehrere) auslagern.
|
|
Sh3va 
Hält's aus hier
Beiträge: 6
|
Verfasst: Mo 09.01.12 15:03
Hmm, okay.
Ich habe nur gehofft, dass es dennoch eine Möglichkeit zur Geschwindigkeitserhöhung gibt.
Wenn man sich anschaut, wie "schnell" die Aufzählung der Ordner,Daten und deren Größe geht, wenn man auf die Eigenschaften eines Ordners geht, dachte ich, man könnte i.wie daran kommen.
Mit Multithreading habe ich mich noch nicht wirklich beschäftigt. Hast du vllt. hilfreiche Links o.ä. wo ich mich reinlesen kann?
Danke aber für deine Antwort!
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mo 09.01.12 15:42
Zitat: | Ich habe nur gehofft, dass es dennoch eine Möglichkeit zur Geschwindigkeitserhöhung gibt. |
Ich habe nicht gesagt das du aus deiner Lösung nicht mehr Geschwindigkeit herausholen kannst sondern nur das der begrenzende Faktor nicht die Programmiersprache sondern die Windows API ist. Und natürlich die Qualität des geschriebenen Codes
Zum Beispiel das ständige Updaten der GUI im Code (GUI ist immer langsam und du rufst ständig die listboxschreiben Methode auf) wird das vermutlich deutlich verlangsamen. Möglicherweise ist DirectoryInfo auch nur eine mäßige Kapselung(insbesondere die GetFiles Methode) und man sollte sich direkt an die Windows API wenden (also FindFirstFile, FindNextFile etc.). Möglicherweise ist dein schreiben in die Xml Datei langsam, weil du ständig in die Datei flushst oder so (habe deinen Code nicht genau inspiziert).
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mo 09.01.12 17:58
Hallo Sh3va
wenn du auch selber deinen Code schlafen legst, ist das ja kein Wunder:
Sh3va hat folgendes geschrieben: |
C#-Quelltext
|
Bei 1000 Dateien wird also schon 1 Sekunde insgesamt gewartet.
Zum Thema "Multithreading" gibt es z.B. folgenden Artikel Multi-Threaded Programmierung
Dann gibt es unter WinForms auch noch den BackgroundWorker, in dessen DoWork-Ereignis du das Auslesen der Dateistruktur durchführen müßtest und in dem ProgressChanged-Ereignis dann das Aktualisieren der GUI stattfinden würde (aber wie von Ralf schon angesprochen, nicht zu häufig - am besten erst die Daten sammeln und dann z.B. jede Sekunde per listBox.AddRange() hinzufügen).
P.S. Außerdem sehe ich gerade noch, daß du ja mehrmals die Ordner durchgehst, in dem du vorher noch DirSize() aufrufst. Selbst wenn du die Ordnergröße zuerst in die XML-Datei schreiben mußt, und danach erst die Dateien und Unterordner, so könntest du die Daten ja cachen. (Würden die Dateien während deines Programmlaufs geändert, z.B. einige gelöscht oder neu hinzugefügt, so würde bei dir ja die Ordnergröße evtl. nicht stimmen.)
Da steckt also noch einiges an Optimierungspotential drin...
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 09.01.12 18:29
Th69 hat folgendes geschrieben : | Bei 1000 Dateien wird also schon 1 Sekunde insgesamt gewartet. |
Um genau zu sein eher mehrere Sekunden, da eine Millisekunde Wartezeit nicht möglich ist.
Das andere generelle Problem:
Du aktualisierst ständig die ListBox, refreshst die, ...
Das kostet enorm Zeit.
Besser ist es, wenn du wie schon erwähnt einen Thread benutzt und nur alle meinetwegen 500 Millisekunden den aktuellen Ordner ausgibst. Und ggf. die Liste um die neuen Einträge ergänzt. Aber die Liste würde ich wenn möglich erst am Ende aktualisieren, weil das relativ viel Zeit kostet. Bei Threads sollte das aber auch besser werden, wenn du das richtig umsetzt.
|
|
Sh3va 
Hält's aus hier
Beiträge: 6
|
Verfasst: Mi 11.01.12 10:43
Danke für die Antworten und die Anregungen.
Ich werde mich damit beschäftigen, sobald ich dann wieder die Zeit habe.
Werde mich sicher nochmal hier melden, um mit euch über meine neuen Ansätze zu diskutieren
ceeyá, Sh3va
|
|
|