| 
| Autor | Beitrag |  
| Sh3va Hält's aus hier
 Beiträge: 6
 
 
 
 
 | 
Verfasst: Mo 09.01.12 13: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 13: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 14: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 14: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: 4800
 Erhaltene Danke: 1059
 
 Win10
 C#, C++ (VS 2017/19/22)
 
 | 
Verfasst: Mo 09.01.12 16: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: 19326
 Erhaltene Danke: 1749
 
 W11 x64 (Chrome, Edge)
 Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
 
 | 
Verfasst: Mo 09.01.12 17: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 09: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 |  |  |  |