Twitter und Facebook-Anbindung
X
Tweet Follow @twitterapi
!!! Anbindung an twitter und facebook öffnen !!!

Wenn Ihnen mein Online-Buch gefällt,
dann bedanken Sie sich doch mit einer kleinen Spende...

30.2 CriticalSections mit Hilfe interner Bibliotheken

30.2 CriticalSections mit Hilfe interner Bibliotheken

Da der Umgang mit der Win API immer ein wenig mühselig ist, hat Microsoft innerhalb von Visual Studio ein paar Klassen bereitgestellt, welche den Zugriff auf die API kapseln. Somit wird der Aufwand ein wenig geringer und auf jeden Fall besser lesbar. Schauen wir uns also das gleiche Beispiel von eben an, nur mit der entsprechenden Klasse der MFC.

 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
					
#define _AFXDLL
#include "afxmt.h"

#include <stdio.h>
#include "ThreadWrapper.h"

struct SMyThreadData {
	int			iStart;
	int			iEnd;
	int			iID;
	CCriticalSection*	pCriticalSection;
};



// Funktion welche durch den Thread ausgeführt wird ///////////////////////////
DWORD ThreadFunc(CThreadWrapper<SMyThreadData>* pThread) {
	__try {
		pThread->GetData().pCriticalSection->Lock();

		for (int iCount = pThread->GetData().iStart; iCount < pThread->GetData().iEnd && !pThread->IsTerminated(); iCount++) {
			printf("Thread: %i - %i\n", pThread->GetData().iID, iCount);
			Sleep(100);
		} // end of for
	} __finally {
		pThread->GetData().pCriticalSection->Unlock();
	} // end of try

	return 0;
} // ThreadFunc ///////////////////////////////////////////////////////////////



// Hauptfunktion der Anwendung ////////////////////////////////////////////////
int main(int argc, char** argv) {
	CCriticalSection*		pCriticalSection	= new CCriticalSection();
	SMyThreadData			sData1			= {0, 10, 1, pCriticalSection};
	SMyThreadData			sData2			= {1000, 1010, 2, pCriticalSection};

	CThreadWrapper<SMyThreadData>*	pThread1		= new CThreadWrapper<SMyThreadData>(&ThreadFunc, sData1);
	CThreadWrapper<SMyThreadData>*	pThread2		= new CThreadWrapper<SMyThreadData>(&ThreadFunc, sData2);

	printf("START\n");

	pThread1->Resume();
	pThread2->Resume();

	// Warten, bis alle Threads fertig sind
	while (!pThread1->IsFinished() || !pThread2->IsFinished()) Sleep(1);

	delete pThread1;
	delete pThread2;

	delete pCriticalSection;
	
	printf("ENDE\n");

	return 0;
} // main /////////////////////////////////////////////////////////////////////
					

Wie Sie in Zeile 1 bis 5 sehen, benutze ich jetzt nicht mehr die "windows.h", sondern eine MFC Bibliothek (Microsoft Foundation Classes C++ Library). Immer wenn man diese Bibliothek einbindet, muss man bestimme Sachen vorher definieren und man darf auch die "windows.h" nicht einbinden, da enthaltene Funktionensdefinitionen indirekt durch die MFC bereitgestellt werden und es ansonsten zu gegenseitigen Includes kommt. In der "afxmt.h" befinden sich eine Reihe von Klassen, mit welchen man Synchronisationen und kritische Abschnitte realisieren kann. Die von mir verwendete Klasse "CCriticalSection" ist beispielsweise von der Klasse "CSyncObject" abgeleitet, welche die Basisklasse der meisten Synchronisationsobjekte ist, welche ich später noch erklären werde.

In den Zeilen 7 bis 12 wird wieder die Struktur für den Thread definiert und im Gegensatz zu vorhin, sieht der Zeiger in Zeile 11 etwas freundlicher aus.

In den Zeilen 17 bis 30 findet man jetzt wieder die Threadfunktion, welche bis auf zwei Kleinigkeiten wieder genauso aussieht. In Zeile 19 sehen Sie jetzt, dass das Betreten des kritischen Abschnittes, sich von einem Funktionsaufruf in ein Methodenaufruf gewandelt hat. Genau das Gleiche passiert auch in Zeile 26 beim verlassen des Abschnittes. Interessanterweise gibt es zum Betreten des Abschnittes wieder zwei Methoden, wobei man der Zweiten ein Timeout übergeben kann, welches bewirkt, dass der Thread maximal eine Zeit X versucht, diesen Abschnitt zu betreten. Dies wird intern wieder über die "TryEnterCriticalSection" Methode gelöst, welche in einer Schleife ausgeführt wird. Ein Timeout gibt es ja eigentlich nicht bei einem kritischen Abschnitt, aber wenn man schon einmal eine Klasse baut, kann man ja ein solches Verhalten mit implementieren, ohne dass man es von Außen mitbekommt.

In der "main" Funktion haben sich auch ein paar Kleinigkeiten geändert. Das Erzeugen des Abschnittswächters in Zeile 36 sieht jetzt, entsprechend dem objektorientierten Ansatz, anders aus. Entsprechend braucht man auch keine Funktion mehr aufrufen um den kritischen Abschnitt freizugeben, sondern löscht einfach das Objekt mit "delete", wie Sie das in Zeile 54 sehen können.

Zum Seitenanfang
Zum Inhaltsverzeichnis

© Copyright by Thomas Weiß, 2009 - 2012