Laden...

Backgroundworker - extrem hoher CPU bedarf - solved

Erstellt von Basher vor 15 Jahren Letzter Beitrag vor 15 Jahren 4.517 Views
B
Basher Themenstarter:in
7 Beiträge seit 2008
vor 15 Jahren
Backgroundworker - extrem hoher CPU bedarf - solved

Hi erstmal =)

Und zwar hab ich mit dem Problem zu kämpfen das nachdem ich eine Aktion in den Backgroundworker gepackt habe das dieser extrem viel länger braucht als wenn ich es normal ausführe, geschätzt sind es geschwindigkeiten von 20x mal schneller im normalen als im backgroundworker.

Die Aktion die getätigt wird ist diese:
Mittels Taglib wird jedes Lied in einem Array getaggt (damit meine ich das die Tags ausgelesen werden)
Diese werden in einer Datenklasse abgespeichert.

Nun weiß ich nicht genau was ich machen soll 😕
die Methode füge ich mal anbei


for (int i = 0; i < _tags.Length; i++)
            {
                try
                {
                    f = TagLib.File.Create(_tags[i].Path);
                    TagLib.Tag t = f.Tag;
                    _tags[i].Artist = "";
                    _tags[i].Genre = "";
                    _tags[i].Album = "";
                    _tags[i].Title = "";
                    if(t.Album != null)
                        _tags[i].Album += t.Album;
                    if (t.Title != null)
                        _tags[i].Title = t.Title;
                    foreach (string artists in t.AlbumArtists)
                            _tags[i].Artist += artists;
                    foreach (string genres in t.Genres)
                            _tags[i].Genre += genres;
                    _tags[i].Length = f.Properties.Duration;
                }
                catch(Exception exc)
                {
                    count++;
                }

            }

würde mich freuen wenn ihr da Tipps hättet

mfg Bash

S
506 Beiträge seit 2006
vor 15 Jahren

thread-priorität?

J
222 Beiträge seit 2006
vor 15 Jahren
Thread.Sleep(50);

in die schleife einbaun verzögert das ganze aber ist wesentlich schonender für die cpu auslastung

B
Basher Themenstarter:in
7 Beiträge seit 2008
vor 15 Jahren

Ok hab den Grund gefunden 🙂


//UIThread
while (!finished)
            {
                finished = st.Readed && st.Tagged;
            }

Readed und Tagged sind boolwerte die angeben ob der Backgroundworker fertig ist, diese werden auf true gesetzt wenn das RunWorkerCompletedEvent abgefeuert wird

Das Problem lag darin das mein UI Thread nichts wirklich besonderes gemacht hat als ebend zu überprüfen ob denn er schon fertig ist, dabei hat er immer die berechnungen interrupted.

heißt soviel wie:

UIThread: fertig ?
Backgroundworker: arbeit
UIThread: fertig ???
Backgroundworker: arbeit
UIThread: fertig ????
UIThread: fertig ?????
Backgroundworker: arbeit

Deshalb hab ich den UIThread nach jeder abfrage für ne viertelsekunde schlafen gelegt =)

danke nochmal für die antworten =)

mfg Bash

X
1.177 Beiträge seit 2006
vor 15 Jahren

huhu,

Warum frägst du im UI-Thread überhaupt ab, ob der BackGroundWorker schon fertig ist, er sagt ja eh im RunWorkerCompletedEvent bescheid!? Hierzu sind ja Events eigentlich da, dass man nicht selbst die ganze Zeit irgendwelche Stati abfragen muss.

🙂

Xynratron

Herr, schmeiss Hirn vom Himmel - Autsch!

Die Erfahrung zeigt immer wieder, dass viele Probleme sich in Luft auslösen, wenn man sich den nötigen Abstand bzw. Schlaf gönnt.

S
443 Beiträge seit 2008
vor 15 Jahren

Ich bin mir nicht ganz sicher, ich habe mich noch nicht in das Thema Threading eingearbeitet, aber feuert der BackGroundWorker nicht ein Event wenn er fertig ist?
RunWorkerCompleted

// edit:
zu langsam, lasse aber den link stehen

mbg
Rossegger Robert
mehr fragen mehr wissen

Montag morgen ist die beste Zeit um eine erfolgreiche Woche zu beginnen

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Basher,

im GUI-Thread sollte man nie warten, egal ob busy waiting (besonders schlimm) oder mit einem blockierenden Aufruf wie Thread.Join und auch nicht mit Thread.Sleep. Einfach nie im GUI-Thread warten. Wenn mans trotzdem tut, hat man gleich die Antwort auf die Frage: [FAQ] Warum blockiert mein GUI?

Die Alternative/Lösung haben ja meine beiden Vorredner schon genannt.

herbivore

0
767 Beiträge seit 2005
vor 15 Jahren

vorallem bringts nichts, wenn man die berechnung dann aus dem GUI thread auslagert (um das UI nicht zu blockieren) wenn man dann das UI blockiert indem man auf den thread wartet.

loop:
btst #6,$bfe001
bne.s loop
rts

B
Basher Themenstarter:in
7 Beiträge seit 2008
vor 15 Jahren

*gg* da hab ich aber was angestellt^^

Erklärung:
die GUI war bei mir nur simuliert, doch haben herbivore und 0815Coder recht das ich mit dem "busy waiting" trotzdem ihn blockiere. Da ich eigentlich nur relativ wenig code fehlt es mir an Erfahrung und somit weiß ich nicht wie ich das umgehe.

Ich weiß es gibt ein Event welches gefeuert wird wenn die Methode fertig ist, ich hab sie auch schon abonniert gehabt, bloß weiß ich mit ihr nicht recht umzugehen. Wenn sie nun gefeuert wird so war meine idee das ich ein bool auf true setze der signalisiert das die methode fertig ist, doch wird diese methode ebend fortlaufend gecheckt was wieder den uithread blockiert.
Andere Ideen hinsichtlich dessen das der UIThread es merkt das der Backgroundworker fertig ist, ohne diese zu blockieren sind willkommen =)

mfg Bash

2.760 Beiträge seit 2006
vor 15 Jahren

Dein BackgroundWorker macht z.B. irgendwelche Berechnungen und wenn diese abgeschlossen sind feuert er das Event woraufhin du dir im Eventhandler die Ergebnise der Berechnung holst und anzeigst.
Eine bool variable brauchst du nicht. Packe einfach alles was du bisher irgendwo nach dem erfolgreichen Abrfagen des bools tust in den eventhandler.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Basher,

naja, die Lösung ist eben RunWorkerCompleted zu verwenden. Alle was getan werden muss, wenn der Thread/BackgroundWorker fertig ist, tut in diesem EventHandler.

Die Methode, die den Worker startet, beendest du einfach sofort danach.

Das ist ereignisgesteuerte Programmierung. Wichtig, dass man das bei Windows-Forms immer so macht.

herbivore

B
Basher Themenstarter:in
7 Beiträge seit 2008
vor 15 Jahren

So wie ich das verstanden habe, ist dies kein ansatz der mir helfen könnte.

Ich wollte GUI - Fachkonzept und Datenhaltungsschicht voneinander trennen, dazu darf zwar die GUI auf die Fachkonzeptschicht zugreifen aber die Fachkonzeptschicht nicht auf die GUI.

Die GUI soll aber trotzdem mitkriegen wann denn der Worker fertig ist damit diese neue Optionen zur Verfügung stellen kann.

Wenn ich es falsch verstanden habe und die Lösung von euch beiden schon genannt wurde, könnte man dann vielleicht ein paar Codeschnippsel vorzeigen damit mir klar wird wie das funktioniert ?

Bash

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Basher,

So wie ich das verstanden habe, ist dies kein ansatz der mir helfen könnte.

dann hast du es falsch verstanden. 🙂

Ich wollte GUI - Fachkonzept und Datenhaltungsschicht voneinander trennen, dazu darf zwar die GUI auf die Fachkonzeptschicht zugreifen aber die Fachkonzeptschicht nicht auf die GUI.

Das ist gut so! Allerdings ist es auch das Normale und schließt daher nichts von dem aus, was wir vorgeschlagen haben.

Die GUI soll aber trotzdem mitkriegen wann denn der Worker fertig ist damit diese neue Optionen zur Verfügung stellen kann.

Ja, bekommt sie ja, indem sie RunWorkerCompleted abonniert.

herbivore

2.760 Beiträge seit 2006
vor 15 Jahren

  BackgroundWorker bw = new BackgroundWorker();
         bw.DoWork += new DoWorkEventHandler(bw_DoWork);
         bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
         bw.RunWorkerAsync();

      void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
      {
         MessageBox.Show((string)e.Result);
      }

      void bw_DoWork(object sender, DoWorkEventArgs e)
      {
         Console.WriteLine("Work!");

         e.Result = "Fertig!";
      }

B
Basher Themenstarter:in
7 Beiträge seit 2008
vor 15 Jahren

genau so wie im codeschnippsel habe ich es gemacht ^^
nun startet aber die Fachkonzeptschicht bei mir selber den Backgroundworker, nicht die GUI, kann die GUI trotzdem den WorkerCompletedEvent abonnieren ?

🙂

2.760 Beiträge seit 2006
vor 15 Jahren

Genau das haben wir versucht dir nahezulegen.

B
Basher Themenstarter:in
7 Beiträge seit 2008
vor 15 Jahren

ui danke ^^

vielen danke euch beiden nochmal 🙂 (und natürlich den anderen im thread gg )

bin nu was essen, danach guck ich mal ob ich das schaffe 🙂

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Basher,

ein neuer Thread/BackgroundWorker, der gestartet wird, um das Blockieren des GUI verhindern soll, sollte natürlich immer vom GUI gestartet werden. Du solltest dein Design entsprechend anpassen.

herbivore