Multithreading
-
Heyho Community,
Ich habe nun schon etwas gesucht, aber irgendwie werde ich nicht fündig bzw. finde keine gescheiten Erklärungen zum Thema (Multithreading).
Ich weiß zwar, das der CreateThread Aufruf einen Thread startet, jedoch kann ich dem doch keine ausführende Funktion übergeben und ich kann mir nicht so recht vorstellen was der Thread ausführt, wenn er aufgerufen wird.
Nun bin ich auch schon auf die Möglichkeit der Benutzung der Funktion AfxBeginThread() gestoßen und habe es auch bereits erfolgreich ausprobiert, aber es gefällt mir nicht so recht. Mein Problem ist, dass ich auf Membervariablen von unterschiedlichen Klassen zu greifen muss. Nun habe ich mir ein Struct gebaut in welchem ich Zeiger auf diese jeweiligen Klassen deklariert habe. Diese Zeiger habe ich dann auch initialisiert und das Struct als LPVOID der AfxBeginThread() Funktion übergeben. Prinzipiell funktioniert es, aber ich finde es sehr unschön mit Zeiger auf Zeiger arbeiten zu müssen.
Ich habe eine "große" bzw. "ober" Funktion (eine OnButton... Funktion), in welcher bis jetzt (ohne Multithreading) alle Rechnungen und Oberflächenaktualisierungen vorgenommen werden. Nun wollte ich diese Funktion einfach in einen Thread packen, also in eine neue Funktion erstellen, die gesamte Funktionalität der OnButton... Funktion herein packen und via AfxBeginThread() aufrufen. Jedoch funktioniert dies natürlich nicht so einfach und ich stieß auf Probleme. Nun habe ich es irgendwie hingebogen, alle UpdateData() Aufrufe auskommentiert und es irgendwie hingefummelt das es erstmal geht. Aber irgendwie bin ich total unzufrieden mit dieser Lösung, weiß aber auf anhieb nicht weiter und bin bissl frustriert.Kennt jemand von euch nen gutes Multithreading Tutorial, eine kurze Einführung in die Grundlagen des Themas oder einfach einen kleinen Crashkurs?
Ich hoffe ihr könnt mir weiterhelfen, trotzdem ich wohl ein sehr spezielles Problem habe.
Grüße,
inva
-
Multithreading ist kein kleines Thema, nix für nen "Crashkurs".
Es gibt ja auch keine Crashkurse für Nuklearphysik...Ansonsten... die beste Kurz-Anleitung zum Thema Threads die es gibt: verwende immer nur einen Thread pro Prozess.
-
Welche Literatur würdet ihr den empfehlen?
Ich war etwas schockiert als ich in der MSDN zu dem Thema nachgeschaut habe und dort nur ein paar Seiten text fand, der mir leider nicht weiter half.Grüße,
-
Nimm mal http://msdn.microsoft.com/library/deu/default.asp?url=/library/DEU/vccore/html/_core_multithreading_with_c.2b2b_.and_mfc.asp als Einstieg.
Ich hatte seinerzeit nur die englische MSDN ;). Dort findest Du aber i.d.R. die besseren Artikel.
Da musst Du Dich einarbeiten. Wie hustbaer schon sagte, nix für schnellen Chrashkurs. Synchronisation, ... (grauseliges, nahezu unerschöpfliches Thema).
Gruss, Gio
-
Ihr übertreibt ja voll. Das ist überhaupt gar nicht schwierig.
-
lolol schrieb:
Ihr übertreibt ja voll. Das ist überhaupt gar nicht schwierig.
Das glauben alle die es nicht verstanden haben.
-
lolol: Ist ein kleiner Junge, des nicht mal weis wie man Multithreading buchstabiert...
-
Danke für die vielen Antworten.
Habe mir schon das Buch "Inside Visual C++ 6.0" ausgeliehen und dort sind die Arbeitsthreads recht gut beschrieben. Zumindest weiß ich schon etwas übers Sync'n, finds echt gut die Threads über Ereignisse zu steuern. Jedoch finde ich es bissl umständlich für 1 Thread 2 CEvents hernehmen zu müssen, einer der den Thread startet und einer der ihn beendet. Aber was solls, danke an Gio für den Link, zwar kenn ich diesen MSDN Artikel schon aber vielleicht schaue ich nochmal genauer rein, hoffentlich finde ich diesesmal was. Weil mein Hauptproblem ist, ich weiß nicht, was ausgeführt wird, wenn ich die CreateThread() Methode aufrufe. Schließlich habe ich doch keine (Arbeits-)Funktion zugeordnet oder ähnliches.Liebe Grüße,
inva*edit*
Vielleicht kann mir jemand bei meinem Problem helfen:
Ich habe eine Arbeitsfunktion, bzw. möchte mir eine Implementieren, jedoch muss diese Funktion zwingend Methoden der Dialogklasse verwenden. Da die Arbeitsfunktion jedoch global und somit außerhalb der Klasse definiert&deklariert ist, bekomme ich hier Zugriffprobleme und ich habe gelesen das es gefährlich ist einfach den this Pointer in der AfxBeginThread Funktion zu übergeben. Jedoch habe ich davon gelesen, dass der Arbeitsthread Nachrichten an den Hauptthread senden kann, wozu er nur die Zugriffsnummer des Fensters brauch. Aber ich will ja nicht mit Hilfe dieser Zugriffsnummer den Hauptthread veranlassen seine Methoden zur Abarbeitung aufzurufen, dann bräucht ich keinen Arbeitsthread ... Den Code kopieren will ich auch nicht... Ich hoffe jemand von euch hat eine Idee bzw. einen Ansatz wie ichder Lösung meines Problems näher komme.
-
Wenn du CreateThread aufrufst wird der Thread Code ausgeführt.
CreateThread(NULL,0,&ThreadProc,this,0,&ThreadId);führt dazu das die Funktion
DWORD WINAPI TFormMain::ThreadProc(LPVOID lpParameter) { return(0); }ausgefürht wird. Wenn diese Funtion das return ausführt ist dein Thread auch wieder beendet. Das heißt mache eine while Schleife rein.
DWORD WINAPI TFormMain::ThreadProc(LPVOID lpParameter) { while(/*Event ThreadExit nicht gesetzt ist*/) { //Thread Code } //Ende Code //Event ThreadNotRunning setzen return(0); }
-
Naja, wenn Du deinen Thread mit AfxBeginThread startest musst Du Doch einen Funtionszeiger übergeben. Das ist deine Threadfuntion.
Bei CWinThread nehm ich InitInstance, mag aber sein, daß es da noch eine bessere Stelle gibt...;)Edit: da war schon jemand schneller

-
Danke maikhaenig, dass hat mir schonmal etwas weitergeholfen.
Jedoch habe ich in dem Code bzw. Programm, das ich Multithreading fähig machen will die Probleme, dass die Methoden der Klasse, eng an die Oberfläche gebunden sind und diese Zeitweise auch, über ein UpdateData(), aktualisieren wollen. Dies jedoch aus einem Arbeitsthread heraus nicht möglich ist.
Da fällt mir spontan ein, ich könnte doch mit Hilfe eine Nachricht aus dem Arbeitsthread heraus den Hauptthread veranlassen die Oberfläche zu aktualisieren, oder?
-
Es ist nicht gefährlich Methoden aus der Dialog Klasse zu verwenden!
Genauer:
- Es ist gefährlich und führt zu Problemen CWnd* aus einem anderen Thread zu verwenden.
- Es ist gefährlich zeitgleich auf Daten zuzugreifen, die zwei (mehrere) Threads gleichzeitig verwenden. Hier muss für eine Synchronisation gesorgt werden.
- Methoden sind nur Code. Solange keine Daten im Spiel sind, ist Code immer thread neutral.
- Es ist grundsätzlich zu überdenken ob Funktionen verwendet werden die Fenster bearbeiten oder Fenstern beeinflussen (SetWindowText etc.), wenn diese Fenster durch einen anderen Thread erzeugt werden. Dies führt zwangsläufig zu einer thread Synchronisation (was gewollt sein kann), oder zu einem Deadlock, wenn der Fenster-Thread keine Nachrichtenschleife ausführt.GUI & multithreading will sehr genau designed werden. Ansonsten bringt ein neuer Thread oft genug nichts.
-
du kommst an deine Metothen uber den Pointer LPVOID lpParameter
DWORD WINAPI Fensterklasse::ThreadProc(LPVOID lpParameter) { while(/*Event ThreadExit nicht gesetzt ist*/) { //Thread Code ((Fensterklasse *)lpParameter)->/*Funktionen oder Variablen*/; } //Ende Code //Event ThreadNotRunning setzen return(0); }Mit den Methoden die das Fenster verändern könnte es zu Problemen kommen.
Dann müßtest du die Message Methode verwenden. Oder das ubere eine Boolsche Variable die beide Threads kennen.z.b.: Hauptprogramm
if (IsNewData) UpdateData();Thread
((Fensterklasse *)lpParameter)->IsNewData=true;Diese Variable dann falls sie in beiden Threads beschrieben wird noch über eine CriticalSection schützen
MfG
-
Danke maikhaenig für den guten Ansatz, ich denke es wäre komfortabler einfach eine globale bool Variable zu nehmen, diese ist dann auch ohne Zeigerverdrehen auf beiden Seiten bekannt. Aber vielen Dank für den Tipp
