Autor Beitrag
Oppi35
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 95
Erhaltene Danke: 3



BeitragVerfasst: 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:

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:
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 user profile iconChristian S.: C#-Tags hinzugefügt
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 15.10.10 09:50 
user profile iconOppi35 hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 95
Erhaltene Danke: 3



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 95
Erhaltene Danke: 3



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 15.10.10 13:10 
user profile iconOppi35 hat folgendes geschrieben Zum zitierten Posting springen:
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
Ein Thread ist per definitionem asynchron. Genau dafür ist ein Thread ja da, dass er parallel zum restlichen Code und dem Hauptthread läuft. Mehr kommt heute Abend nach der Arbeit... ;-)
danielf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1012
Erhaltene Danke: 24

Windows XP
C#, Visual Studio
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 95
Erhaltene Danke: 3



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1012
Erhaltene Danke: 24

Windows XP
C#, Visual Studio
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 95
Erhaltene Danke: 3



BeitragVerfasst: 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:)))




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:
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";
            
            /*Synchroner Teil*/
            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");
            
            /*Asynchroner Teil*/
            del.BeginInvoke(nullnull);
            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 user profile iconKha: Tags korrigiert
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: So 14.11.10 00:15 
user profile iconOppi35 hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1012
Erhaltene Danke: 24

Windows XP
C#, Visual Studio
BeitragVerfasst: 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ß