Autor |
Beitrag |
Oppi35
      
Beiträge: 95
Erhaltene Danke: 3
|
Verfasst: Fr 15.10.10 09:45
Ich arbeite mich derzeit in die Threadprogrammierung ein und habe hier mal eine Frage zu folg. recht simplen Code:
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:
| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading;
namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Thread thread = new Thread(doit); thread.Start(); for (int x = 0; x < 100; x++) { Console.WriteLine("Hauptthread " + x); } thread.Join(); Console.WriteLine("Beide Threads fertig"); Console.Read(); } static void doit() { for (int i = 0; i < 100; i++) { Console.WriteLine("Methode Doit " + i); } } } } |
Auf dem Bildschirm erscheint ca. 4 bis 5 mal "Hauptthread", dann wieder 4-5 mal "Methode Doit", dann wieder von vorne usw. bis die Schleife beendet ist. Am Ende erscheint dann "Beide Threads fertig".
Meine Frage:
Ich habe lt. Lektüre synchrone Bearbeitung so verstanden, dass erst ein Thread bearbeitet wird, bevor der nächste gestartet wird. Nach meinem bisherigen Verständnis wird in dem Code doch zuerst der Thread mit der Methode "Doit" gestartet. Warum wird der nicht erst beendet, bevor der Hauptthread weiterläuft? Es handelt sich doch hier um einen synchronen Methodenaufruf, oder?
Oder arbeitet ein Hauptthread anders als ein separat erzeugter Thread (da er ja schon läuft und nicht neu gestartet wird)?
So wie das Programm hier abläuft, stelle ich mir eigentlich die asynchrone Abarbeitung des Programms bzw. der Threads vor.
Wo ist mein Denkfehler?
Für Eure Hilfe schon vorab Vielen Dank.
Gruß
Frank
Moderiert von Christian S.: C#-Tags hinzugefügt
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 15.10.10 09:50
Oppi35 hat folgendes geschrieben : | Warum wird der nicht erst beendet, bevor der Hauptthread weiterläuft? |
Mit Start startest du den Thread (bzw. sagst dem Betriebssystem, dass er gestartet werden soll). Dieser läuft dann parallel zu deinem Hauptthread. Mit Join wartest du dann auf die Beendigung des zweiten Threads.
Vorher laufen beide parallel, je nach Zuteilung des Betriebssystems können sich die Ausgaben also derweil auch mischen.
|
|
Oppi35 
      
Beiträge: 95
Erhaltene Danke: 3
|
Verfasst: Fr 15.10.10 09:55
Ok, und was wäre der Unterschied zu einem asynchronen Aufruf?
Vielen Dank erstmal für Deine Antwort  )
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 15.10.10 11:01
Dass du Join weglässt. Dann läuft der zweite Thread einfach vor sich hin und benachrichtigt dann z.B. das Hauptprogramm, wenn er fertig ist und z.B. Ergebnisdaten fertig hat.
|
|
Oppi35 
      
Beiträge: 95
Erhaltene Danke: 3
|
Verfasst: Fr 15.10.10 12:36
Vielen Dank, aber leider beantwortet das nicht meine Frage.
Ich versuche es nochmal anders zu formulieren:
Für asynchrone Aufrufe verwendet man doch z.B. Delegate.BeginInvoke...
Das Starten des Threads in meinem Code hat doch nichts mit asynchronem Methodenaufruf zu tun, auch wenn ich den Join Befehl nicht verwende. Oder täusche ich mich hier?
Und bei einem synchronen Methodenaufruf dachte ich, dass erst der aufgerufene Thread ausgeführt wird und dann der Nächste.
Wie aber mein Code zeigt, wird bei dem einfachen Aufruf der Thread.Start() Methode scheinbar asynchron gearbeitet. Warum? Und was ist der Unterschied zu einem asynchronen Aufruf mit z.B. Begininvoke()???
Wenn mir das jemand etwas ausführlicher erklären könnte, wäre ich hier sehr dankbar.
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 15.10.10 13:10
|
|
danielf
      
Beiträge: 1012
Erhaltene Danke: 24
Windows XP
C#, Visual Studio
|
Verfasst: Fr 15.10.10 15:38
Ja, versuche es am besten mit den Grundlagen. Dafür gibt es viel Material, zum Beispiel das Buch C#.
Man sollte Klasse & Methoden nicht verwenden wenn man nicht weis wieso... ein Schritt nach dem Anderen, sonst klappt es nicht.
Gruß
|
|
Oppi35 
      
Beiträge: 95
Erhaltene Danke: 3
|
Verfasst: Fr 15.10.10 16:09
Hallo Danielf,
danke für den Tip. Dass mache ich schon seit langer Zeit und werde es auch in Zukunft weiter konsequent verfolgen.
Ich benötige allerdings derzeit bei der Arbeit ein Programm, dass in WPF in einer längeren Schleife auch weiterhin bedienbar bleibt. Ist kein sonderlich schweres Programm, aber es sollte halt diese Eigenschaft haben. Von daher beschäftige ich mich derzeit intensiv mit diesem Thema.
Im übrigen benutze ich das Visual C# 2010 Buch ISBN 978-3-8362-1552-7. Das Thema ist schon recht detailliert beschrieben, aber eine Antwort auf meine Frage konnte ich leider nicht finden.
|
|
danielf
      
Beiträge: 1012
Erhaltene Danke: 24
Windows XP
C#, Visual Studio
|
Verfasst: Fr 15.10.10 16:19
Wie bereits geschrieben: Threads lagern Aufgaben aus und so kann das Hauptprogramm weiter bedient werden. Invoke hingegen synchronisiert ein aktuelles Control mit dem WindowHandle (also das Gegenteil!). Wenn du keine GUI Interaktion hast reicht dir ein Thread völlig.
Gruß
|
|
Oppi35 
      
Beiträge: 95
Erhaltene Danke: 3
|
Verfasst: So 14.11.10 00:03
Hallo,
leider ist mir noch einiges unklar. Zum nachvollziehen meines Verständnisproblems habe ich den Code unterteilt in einen synchronen- und in einen asynchronen Teil.
Zur Info: Ich arbeite an einem Einprozessor-PC.
An dem Ergebnis des Codes kann ich keinen deutlichen Unterschied zwischen synchronem und asynchronem Methodenaufruf feststellen.
Dass es funktioniert, weiß ich (z.B. WPF; Userinterface bleibt bedienbar).
Nur warum. Ein Einprozessor-PC kann, soweit mir bekannt ist, zu einem bestimmten Zeitpunkt nur einen Thread bearbeiten. Sofern eine Methode synchron aufgerufen wird, gibt der Thread nach einer bestimmten Zeit die Steuerung wieder ab.
So wie in meinem Beispielcode zu sehen ist, macht doch aber der asynchrone Aufruf auch nichts anderes, außer dass nach dem asynchronen Aufruf mit Begininvoke sofort wieder in den Hauptthread zurückgekehrt wird.
Kann mir jemand den Unterschied verständlich erklären? Wie gesagt, ich weiß dass es funktioniert und auch wie. Nur mache ich ungern Sachen, die ich nicht verstehe warum:)))
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:
| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading;
namespace Thread1 { class Program { static void Main(string[] args) { Thread.CurrentThread.Name = "Hauptthread";
demo dem = new demo(); ThreadStart del; del = new ThreadStart(dem.Doit); Thread thread1 = new Thread(del); thread1.Name = "Thread1";
Thread thread2 = new Thread(del);
thread2.Name = "thread2"; thread1.Start(); thread2.Start(); for (int i = 0; i < 500; i++) { Console.WriteLine(Thread.CurrentThread.Name); }
thread1.Join(); thread2.Join();
Console.WriteLine("Fertig mit allem"); del.BeginInvoke(null, null); Console.WriteLine("Asynchron wurde gestartet!"); for (int i = 0; i < 100; i++) { Console.WriteLine(Thread.CurrentThread.Name+" Asynchron"); } Console.Read(); }
} class demo { public void Doit() { for (int i = 0; i < 100; i++) { Console.WriteLine(Thread.CurrentThread.Name); } } }
} |
Moderiert von Kha: Tags korrigiert
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: So 14.11.10 00:15
Oppi35 hat folgendes geschrieben : | So wie in meinem Beispielcode zu sehen ist, macht doch aber der asynchrone Aufruf auch nichts anderes, außer dass nach dem asynchronen Aufruf mit Begininvoke sofort wieder in den Hauptthread zurückgekehrt wird. |
Das macht Thread.Start genauso. Der einzige Unterschied zwischen den beiden ist der, dass BeginInvoke einen Threadpool- und Start einen ganz neuen Thread verwendet. Vom Verhalten her sind deine beiden Code-Teile gleich, nämlich mit synchroner Schleife im Hauptthread und asnychronen Schleifen in einem oder zwei Nebenthreads; das Invoke dürfte ja wahrscheinlich gar nicht zum Zuge kommen, weil die Hauptschleife sowieso am längsten läuft. Ich bin mir nicht sicher, was du uns demonstrieren willst.
_________________ >λ=
|
|
danielf
      
Beiträge: 1012
Erhaltene Danke: 24
Windows XP
C#, Visual Studio
|
Verfasst: So 14.11.10 12:20
Du benötigst nicht mehrere Prozessoren. Es ist zwar richtig, dass einer jeweils nur eine Aufgabe abarbeiten kann. Allerdings verteilt dein Betriebssytem die Aufgaben so schnell, dass es für dich wie eine parallel Verarbeitung aussieht.
Gruß
|
|