Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Threads und Priorität
steffen_dec
myCSharp.de - Member



Dabei seit:
Beiträge: 322

Themenstarter:

Threads und Priorität

beantworten | zitieren | melden

Hallo Leute,

mein Beispiel klappt irgendwie nicht ganz nach der Theorie der Priorität... oder ich hab ein Denkfehler


        Thread t1;
        Thread t2;
        Thread t3;
        
        private void cmdTestThreading_Click(object sender, EventArgs e)
        {
            
            t1 = new Thread(new ThreadStart(fred1));
            t2 = new Thread(new ThreadStart(fred2));
            t3 = new Thread(new ThreadStart(fred3));
            listBox1.Items.Clear();
            t1.Priority = ThreadPriority.Highest;
            t2.Priority = ThreadPriority.BelowNormal;
            t3.Priority = ThreadPriority.Lowest;
            
            t1.Start();
            t2.Start();
            t3.Start();           
        }

        void fred1()
        {
            for (int i = 0; i ≤ 100; i++)
            {
                    AddText("1111" + " => " + i.ToString());
            }
        }

        void fred2()
        {
            for (int i = 0; i ≤ 100; i++)
            {
                    AddText("2222" + " => " + i.ToString());
            }
        }

        void fred3()
        {
            for (int i = 0; i ≤ 100; i++)
            {
                    AddText("3333" + " => " + i.ToString());
            }
        }

        private void AddText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.listBox1.InvokeRequired)
            {
                AddTextCallback d = new AddTextCallback(AddText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.listBox1.Items.Add(text);
            }
        }

wenn ich die Priorität auf standard lasse dann erhalte ich immer:
Zitat
1111 => 0
2222 => 0
3333 => 0
1111 => 1
2222 => 1
3333 => 1
1111 => 2
2222 => 2
3333 => 2
... usw

wenn ich die Prioritäten wie oben im Code setze dann kriege ich diese Reihenfolge:
Zitat
1111 => 0
1111 => 1
1111 => 2
2222 => 0
3333 => 0
1111 => 3
2222 => 1
3333 => 1
1111 => 4
2222 => 2
3333 => 2
1111 => 5
...usw
wobei sich die Reihenfolgen bei jedem aufruf auch bisschen ändert...

müsste theoretisch nicht diese Reihenfolge rauskommen?
Zitat
1111 => 0
1111 => 1
1111 => 2
...
1111 => 99
1111 => 100
2222 => 0
2222 => 1
2222 => 2
...
2222 => 99
2222 => 100
3333 => 0
3333 => 1
3333 => 2
....
3333 => 99
3333 => 100

Ich möchte praktisch dass Thread1 die höchste Priorität hat, und ich ihn jederzeit starten kann (ohne warten zu müssen) die anderen Threads müssen dann solange warten bis Thread1 fertig ist

Man kann ja jetzt einfach die anderen Task auf suspend stellen, aber dass ist ja auch nicht das ware, weil ich dann später z.b. 11 oder noch mehr Threads habe...

Vielen Dank für Eure Anregungen.

MFG
Steffen
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo steffen_dec,

Control.Invoke provoziert einen Thread-Wechsel. Das bringt so ziemlich alles durcheinander. Verwende mal Control.BeginInvoke.

herbivore
private Nachricht | Beiträge des Benutzers
steffen_dec
myCSharp.de - Member



Dabei seit:
Beiträge: 322

Themenstarter:

beantworten | zitieren | melden

Hallo herbivore,

danke für deinen Beitrag!

stimmt es so?


private void AddText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.listBox1.InvokeRequired)
            {
                AddTextCallback d = new AddTextCallback(AddText);
                this.BeginInvoke(d, new object[] { text });
                //this.Invoke(d, new object[] { text });
            }
            else
            {
                this.listBox1.Items.Add(text);
            }
        }

so sieht es schon besser aus, aber dennoch springt manchmal Thread2 rein

ich bin noch Anfänger in C# und .Net

Gruß
Steffen
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo steffen_dec,

eine höhere Priorität verhindert nicht, dass Prozesse/Threads mit geringerer Priorität auch ab und zu mal drankommen. Sonst würde ein Prozess mit hoher Priorität das ganze System lahmlegen. Ist also alles ok.

herbivore
private Nachricht | Beiträge des Benutzers
steffen_dec
myCSharp.de - Member



Dabei seit:
Beiträge: 322

Themenstarter:

beantworten | zitieren | melden

Hallo herbivore,

heißt es dass ich nicht drum rum komme, die anderen Threads (zumindest die von meinem Programm) in suspend-Modus setze und am Ende wieder resume!?

So wäre ich auf der sicheren Seite oder?

Danke nochmal für deine Aufklärung :-)

Gruß
Steffen
private Nachricht | Beiträge des Benutzers
talla
myCSharp.de - Experte

Avatar #avatar-3214.jpg


Dabei seit:
Beiträge: 6.862
Herkunft: Esslingen

beantworten | zitieren | melden

Wozu überhaupt Threads wenn die Aktionen hintereinander ausgeführt werden sollen? Wenns darum geht das z.B. die GUI nicht blockieren soll, dann ists doch einfacher nur einen Thread zu starten und dort halt die Aktionen hintereinander auszuführen.
Baka wa shinanakya naoranai.

Mein XING Profil.
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo steffen_dec,

wenn du willst, dass Threads bestimmte Aktionen nicht gleichzeitig machen, musst du sie synchronisieren. Das ist ein Thema für sich und da kommt man nicht drum rum sich gründlich einzuarbeiten. Suspend und Resume wären ein schlechtes Mittel, zumal diese Methoden depricated sind. Normalerweise wird mal lock verwenden. Man kann aber auch AutoResetEvent o.ä. verwenden, je nach den konkreten Anforderungen.

Wenn du aber nur willst, dass deine Aufgaben nacheinander abgearbeitet werden, dann pack sie doch einfach in einen Thread. :-)

herbivore
private Nachricht | Beiträge des Benutzers
steffen_dec
myCSharp.de - Member



Dabei seit:
Beiträge: 322

Themenstarter:

beantworten | zitieren | melden

Hallo,

Lock dient doch dazu, damit die Threads einen Code-Abschnitt nicht gleichzeitig ausführen oder?

Ich kann es nicht in einen Thread packen, da das ganze über einen(bzw. mehrere) Event (Interrupt von einer I/O-Karte) gesteuert wird, und bei einem bestimmten Event muss ich was höher prioritäres (sagt man es so ) erledigen.

Gruß
Steffen
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo steffen_dec,

Windows ist eh kein Echtzeit-Betriebssystem. Wenn du was höher priorisiertes tun willst, dann setzte die Priorität hoch. Vermeiden, dass Windows statt deiner wichtigen Aufgaben lieber was anderes tut, kannst du eh nicht.

herbivore
private Nachricht | Beiträge des Benutzers
steffen_dec
myCSharp.de - Member



Dabei seit:
Beiträge: 322

Themenstarter:

beantworten | zitieren | melden

Hallo,

ja dass ist mir schon klar, ich dachte dass ich damit wenigstens meine eigenen Threads in Griff hätte in dem ich die Priorität anders vergebe...

mal sehen wie sich das auswirkt wenn ich schon soweit bin...

Gruß
Steffen
private Nachricht | Beiträge des Benutzers
talla
myCSharp.de - Experte

Avatar #avatar-3214.jpg


Dabei seit:
Beiträge: 6.862
Herkunft: Esslingen

beantworten | zitieren | melden

Dann bleibt dir wohl nur Threadsynchronisation um wenigstens in deinen Threads ne Priorisierung hinzubekommen.
Baka wa shinanakya naoranai.

Mein XING Profil.
private Nachricht | Beiträge des Benutzers
Borg
myCSharp.de - Member



Dabei seit:
Beiträge: 1.529
Herkunft: Berlin, Germany

beantworten | zitieren | melden

Zur Klärung:
Windows verteilt Prozessorzeit mittels preemptiven Multitaskings. Das bedeutet, jeder Thread bekommt einen Zeitrahmen (Standard: 50ms), ist dieser beendet, wird der Thread angehalten und der nächste wiederaufgenommen.
Ein Thread kann drei schedulerrelevante Status haben: Running, Ready To Run oder Waiting.
Es gibt pro Prozessor nur einen Thread mit dem Status "Running". Dies ist der gerade ausgeführte. Wenn der nächste zum Zuge kommen soll, sucht der Scheduler nach Threads mit dem Status "Ready To Run" und führt denjenigen mit der höchsten Priorität aus (Status wird zu "Running"). Ist der Zeitrahmen vorbei (bzw. wird beendet), wird dieser Thread auf den Status "Ready To Run" gestellt und ein Flag gesetzt, dass er in diesem Durchlauf bereits lief.
Gibt es mehrere Threads mit gleicher Priorität wird derjenige ausgeführt, der noch kein gesetztes Flag hat. Gibt es einen solchen nicht, wird das Flag bei allen wieder entfernt.
Der Status "Waiting" wird durch bestimmte Systemfunktionen vergeben, die größtenteils ein Wait im Namen tragen. Oder auch durch Control.Invoke. Er besagt, dass der Thread zwar noch läuft, momentan jedoch nicht ausgeführt werden braucht, da er auf den Abschluß einer Aktion wartet.

Damit ist klar, warum so eine scheinbar merkwürdige Reihenfolge herauskommt.
Alle Threads beenden ihren Zeitrahmen beim Aufruf von Control.Invoke. Da sie die gleiche Priorität haben, werden sie reihum ausgeführt.
Haben sie jetzt unterschiedliche Prioritäten, so kommen die niedriger priorisierten nur dann zum Zuge, wenn alle höheren nichts zu tun haben.
Allerdings kann das Laufzeitverhalten jetzt nicht mehr vorhergesagt werden, da ja nicht genau bekannt ist, wann die per Control.Invoke in einem anderen Thread gestartetet Methode beendet ist und der Thread wieder zu "Ready To Run" zurückkehrt. In genau diesen Zeiten kommt ein niedriger priorisierter Thread zum Zug, auch er bleibt beim Control.Invoke hängen und macht "Platz" für den nächsten.

Da es jetzt aber noch ganz viele andere Threads anderer Prozesse auf dem System gibt, ist das wirkliche Verhalten noch viel komplexer.
private Nachricht | Beiträge des Benutzers
svenson
myCSharp.de - Member



Dabei seit:
Beiträge: 8.746
Herkunft: Berlin

beantworten | zitieren | melden

Deswegen Finger weg von den Thread-Prioritäten.
private Nachricht | Beiträge des Benutzers
steffen_dec
myCSharp.de - Member



Dabei seit:
Beiträge: 322

Themenstarter:

beantworten | zitieren | melden

Hallo,

die Prioritäten sind doch da um diese zu nutzen, warum also nicht??

Danke Borg, so gehts nun einwandfrei


Thread t1;
        Thread t2;
        Thread t3;
        private ArrayList liste = new ArrayList();

        private void cmdTestThreading_Click(object sender, EventArgs e)
        {
            
            t1 = new Thread(new ThreadStart(fred1));
            t2 = new Thread(new ThreadStart(fred2));
            t3 = new Thread(new ThreadStart(fred3));
            listBox1.Items.Clear();
            t1.Priority = ThreadPriority.Highest;
            t2.Priority = ThreadPriority.BelowNormal;
            t3.Priority = ThreadPriority.Lowest;
            
            t1.Start();
            t2.Start();
            t3.Start();
            t1.Join();
            t2.Join();
            t3.Join();

            listBox1.Items.AddRange(liste.ToArray());
        }

        void fred1()
        {
            for (int i = 0; i ≤ 100; i++)
            {
                liste.Add("1111" + " => " + i.ToString());
            }
        }

        void fred2()
        {
            for (int i = 0; i ≤ 100; i++)
            {
                liste.Add("2222" + " => " + i.ToString());
            }
        }

        void fred3()
        {
            for (int i = 0; i ≤ 100; i++)
            {
                liste.Add("3333" + " => " + i.ToString());
            }
        }

private Nachricht | Beiträge des Benutzers
banzai
myCSharp.de - Member

Avatar #avatar-2501.jpg


Dabei seit:
Beiträge: 57
Herkunft: Deutschland / NRW

beantworten | zitieren | melden

Zitat
Original von steffen_dec
Hallo,

die Prioritäten sind doch da um diese zu nutzen, warum also nicht??

Tja, weil´s halt nicht deterministisch ist - s.o.
In einer komplexeren Applikation (= viele Threads) können hoch-priore Threads auch zu interessanten Seiteneffekten, wie z.B. "Blockaden", führen. Und die dann aufzuklären - viel Spaß !
2 + 2 = 5 for large values of 2
private Nachricht | Beiträge des Benutzers
svenson
myCSharp.de - Member



Dabei seit:
Beiträge: 8.746
Herkunft: Berlin

beantworten | zitieren | melden

So isses. Zudem: Was bringt es? Schneller wird davon i.d.R. nix. In jedem Fall ist es kein Mittel zur Ablaufsteuerung.
private Nachricht | Beiträge des Benutzers