Autor Beitrag
augiaugi
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Sa 04.02.12 14:58 
Hi Leute

Ich versuch mir grad eine Funktion zu schreiben die mir so schnell wie möglich alle Datein (in meinem Fall mit dem Suchmuster "*.mp3") in einer List<Tracks> speichert.
Tracks ist eine von mir geschriebene Klasse in der ich dem Objekt die Attribute string Titel, string Artist, string Album, int Year, string Filepath setzen kann.
Aber sobald ich einen Ordner durchsuche der eine graoße Anzahl an mp3 Datein aufweist bekomme ich die folgende Exception:
"Der Thread wird ausgeführt oder wurde abgebrochen. Neustart nicht möglich."
Die Exception tritt in Zeile 81 ein.
Kann mir da bitte jemand helfen??

Danke mfg augi

ausblenden volle Höhe C#-Quelltext
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:
        public static List<Track> all_Tracks = new List<Track>();

        static public List<Track> getallTracksRecusiv(string _directory)
        {
            all_Tracks.Clear();
            getFilesfromPath(_directory);
            getDirectorys(_directory);
            //Wartet bis alle Threads geschlossen sind
            while (ThreadDirectory.IsAlive)
            {
                while (ThreadFilesFromPath.IsAlive)
                {
                    Thread.Sleep(100);
                }
            }
            return all_Tracks;
        }

        static public List<Track> getallTracks(string _directory)
        {
            all_Tracks.Clear();
            getFilesfromPath(_directory);
            //Wartet bis alle Threads geschlossen sind
            while (ThreadDirectory.IsAlive)
            {
                while (ThreadFilesFromPath.IsAlive)
                {
                    Thread.Sleep(100);
                }
            }
            return all_Tracks;
        }

        static public Thread ThreadDirectory;
        static private void getDirectorys(object _directory)
        {
            try
            {
                foreach (string directory in Directory.GetDirectories(_directory.ToString()))
                {
                    try
                    {
                        ThreadDirectory = new Thread(function_track.getFilesfromPath);
                        try
                        {
                            ThreadDirectory.Start(directory);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("[ThreadDirectory] ThreadStart: " + e.Message);
                        }
                        getDirectorys(directory);
                    }
                    catch (ThreadStateException e)
                    {
                        Console.WriteLine("\n[" + directory + "]\nThreadDirectory: {0}\n", e.Message);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("\ngetDirectorys: {0}\n", e.Message);
            }
        }

        static public Thread ThreadFilesFromPath;
        static private void getFilesfromPath(object _searchpath)
        {
            List<string> filelist = new List<string>();
            try
            {
                foreach (string file in Directory.GetFiles(_searchpath.ToString(), "*.mp3"))
                {
                    try
                    {
                        ThreadFilesFromPath = new Thread(function_track.getFileInformation);
                        try
                        {
                            ThreadFilesFromPath.Start(file);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("[ThreadFilesFromPath] ThreadStart: " + e.Message);
                        }
                    }
                    catch (ThreadStateException e)
                    {
                        Console.WriteLine("\n[" + file + "]\nThreadFilesFromPath: {0}\n", e.Message);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("\ngetFilesfromPath: {0}\n", e.Message);
            }
        }

        static private void getFileInformation(object _filepath)
        {
            Mp3Info mp3Info = new Mp3Info();
            string[] FileInformation = new string[5];
            try
            {
                mp3Info.Read(_filepath.ToString());
                if (mp3Info.ContainsID3v1Information)
                {
                    Track buffer = new Track(mp3Info.Title.Replace("\0"""), mp3Info.Artist.Replace("\0"""), mp3Info.Album.Replace("\0"""), mp3Info.Year,_filepath.ToString());
                    all_Tracks.Add(buffer);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("\ngetFileInformation: {0}\n", e.Message);
            }
        }
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 04.02.12 15:42 
Wieviel ist viel? Es ist nicht besonders Clever tausende von Threads zu erzeugen. Threads haben einen Resourcenoverhead (z.b. einen eigenen Stack von ich glaube standardmäßig 1MB) dir werden also schlicht irgendwann die Systemresourcen ausgehen. Mal ausgenommen das ab einer gewissen Anzahl Threads dein Programm durch mehr Threads nicht schneller wird sondern nur noch mit Contextswitching zwischen den Threads beschäftigt ist und nicht mehr mit den eigentlichen Aufgaben. Du solltest also die Anzahl gleichzeitig laufender Threads begrenzen. Sie dir dazu zum Beispiel den Threadpool an.

Für diesen Beitrag haben gedankt: augiaugi
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 04.02.12 15:53 
Hallo augiaugi :welcome:

sei mir nicht böse, aber dein Code ist total falsch.
Ich weiß, daß du dir von den Threads einen Geschwindigkeitsvorteil erhoffst, aber erstens ist das in deinem Fall nicht so (denn der größte Teil ist IO, d.h. Plattenzugriff) und zweitens muß man sich mit Threadprogrammierung gut auskennen.
Ein guter Einstieg ist als PDF-Datei unter Multi-Threaded Programmierung zu finden.

Dein eigentlicher Fehler ist, daß du nur eine statische Variable benutzt und diese kann natürlich während des Ablaufs sich ändern, d.h. zwischen den Zeilen
ausblenden C#-Quelltext
1:
2:
3:
ThreadFilesFromPath = new Thread(function_track.getFileInformation);
// ...
ThreadFilesFromPath.Start(file);

kann ein Threadwechsel erfolgen, so daß ThreadFilesFromPath dann auf eine Instanz eines anderen (schon gestarteten) Threads zeigt.

Falls du schon mit VS 2010 und .NET 4 programmierst, kann ich dir nur zur TPL bzw. dessen Tasks raten, denn dann brauchst du dich selber nicht um eigene Thread zu kümmern (einen kurzen Überblick gibt es als Powerpoint-Presentation von mir unter www.c-sharp-forum.de...php?p=604486#604486).

Beim Auslesen der Directories und Files jedoch verzichte komplett auf Threads!
augiaugi Threadstarter
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Sa 04.02.12 17:39 
Danke Th69 für deinen Rückmeldung,

bin dir ned böse ... ,hab noch nie mit Threads gearbeitet und wollte mir so einen Geschwindigkeits erhöhung rausholen.
Aber was ich nicht verstehe ist wie ich sonnst eine halbwegs schnelle Durchsuchung realisieren soll....
Ich hab nähmlich Tests durchgeführt in dem rausgekommen ist das ich mit Threads um das 7 Fache schneller bin als wenn ich es ohne Threads Programmiere..
Wäre für ein Beispiel sehr froh...

mfg augi
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 04.02.12 18:48 
Hallo,

hast du denn einen 8x-Core (bzw. einen Quad-Core mit Hyperthreading), denn nur dann wäre ein Geschwindigkeitsvorteil von ca. 7x zu erwarten?

Mit der TPL wäre es jedenfalls deutlich weniger Code. Als Einsteig kannst du dir mal die MSDN unter Task Parallel Library bzw. das entsprechende Kapitel im OpenBook Visual C# 2010 - Kapitel 11 Die TPL durchlesen bzw. am besten sogar die Beispiele selber austesten.

Bei dir könnte es in etwa dann so aussehen (ich habe den Code jetzt nicht bei mir getestet ;-)):
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
void ShowFilesAndDirectories(string directory)
{
  Parallel.ForEach(Directory.GetDirectories(directory), // bzw. EnumerateDirectories
      dic =>
      {
          Console.WriteLine(dic);
          ShowFilesAndDirectories(dic);
      });

  Parallel.ForEach(Directory.GetFiles(directory, "*.mp3"), // bzw. EnumerateFiles
      file =>
      {
         Console.WriteLine(file);
      });
}

Bedenke, daß die einzelnen Directories und Files nun in unsortierter Reihenfolge ausgegeben werden. Wenn du erst die Files (Dateien) ausgeben willst, dann vertausche einfach die beiden Parallel.ForEach-Schleifen.

Falls dir die Lambda-Ausdrücke (... => { ... }) (noch) nichts sagen, dann schau mal in Delegaten und Lambda-​Ausdrücke.