Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

31

21.01.2008, 23:58

Zitat von »"$nooc"«

eine frage..

kann man typedef in einer klasse verwenden?


ja, nur das WINAPI ist falsch. WINAPI steht für die aufrufkonvention __stdcall, memberfunktionen verwenden aber eine eigene aufrufkonvention (MSVC bezeichnet die als __thiscall).

wenn, dann so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class blub
{
public:

  // ...

  DWORD ThreadProc(LPVOID);

  // ...

  typedef DWORD (blub::*ptrToThreadProc) (LPVOID);
};

// ...


blub::ptrToThreadProc hallo = &blub::ThreadProc;


allerdings denk ich, dass diese konkrete methode eine statische wird sein müssen...für statische methoden nimmst du normale funktionspointer (weil die keinen this pointer bekommen):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class blub
{
public:

  // ...

  static DWORD WINAPI ThreadProc(LPVOID);

  // ...

  typedef DWORD (WINAPI *ptrToThreadProc) (LPVOID);
};

// ...


blub::ptrToThreadProc hallo = &blub::ThreadProc;


wenn du aber windows.h inkludierst is das sowieso nicht notwendig, da es dort bereits eine derartiges typedef gibt, nennt sich LPTHREAD_START_ROUTINE. ;)

achja: um dir kopfzerbrechen zu ersparen verrat ich dir an dieser stelle gleich, dass du eine nicht statische memberfunktion nicht an CreateThread() übergeben kannst (weil normale funktionspointer und pointer auf member nicht kompatibel sind, eben aufgrund dieser sache mit dem this pointer)...

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

32

22.01.2008, 09:20

:lol: irgendwie hatte ich schon das gefühl dass es so ist.. :D


LPTHREAD_START_ROUTINE ist die funktionsignatur auf die ich einen pointer gebraucht hätte..


aaalso.. das is das erste mal dass ich mit einer statischen funktion arbeite..
ich vermute dass sich eine statische funktion gleich wie eine statische variable verhält oder?

Zitat von »"dot"«


achja: um dir kopfzerbrechen zu ersparen verrat ich dir an dieser stelle gleich, dass du eine nicht statische memberfunktion nicht an CreateThread() übergeben kannst (weil normale funktionspointer und pointer auf member nicht kompatibel sind, eben aufgrund dieser sache mit dem this pointer)...


das ist wirklich eine äußerst wertvolle information.. danke :D



*EDIT:

also, ich hab das jetzt zusammengebracht.. hab der funktion CreateThread() einen gültigen funktionszeiger übergeben..

mein problem:
die übergebene funktion wird nur 1mal aufgerufen, und dann ist schluss..

also.. zumindest im debug modus kehr das programm kein zweites mal mehr zu dieser funktion zurück..


*EDIT2:

ich hab das programm jetzt mal ausgeführt, und dann den prozess angehalten ... und da hab ich bemerkt, dass mein programm die ganze zeit in einer zeile stehn bleibt..

nämlich bei der hauptschleife meines programms

nachdem ich einen thread erstellt habe, hängt das ganze genau da:

C-/C++-Quelltext

1
2
3
4
5
6
    MSG msg;
    while(GetMessage (&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }


die parameter von msg sind alle '0' ..
wenn ich einen haltepunkt bei TranslateMessage() setze, sehe ich dass das programm diese zeile nicht mehr passiert..

woran kann das liegen? hab ich beim erstellen des threads evtl. was falsch gemacht?
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

33

22.01.2008, 13:09

Zitat von »"$nooc"«

also, ich hab das jetzt zusammengebracht.. hab der funktion CreateThread() einen gültigen funktionszeiger übergeben..

mein problem:
die übergebene funktion wird nur 1mal aufgerufen, und dann ist schluss..

also.. zumindest im debug modus kehr das programm kein zweites mal mehr zu dieser funktion zurück [...]


ich hab ka was du damit sagen willst. evtl. wärs hilfreich entweder zu skizzieren was du eigentlich erreichen willst oder etwas code von diesem programm zu posten ;)

oder kann es sein dass du eine etwas falsche vorstellung von threads hast?
thread bedeutet nicht, dass da diese ThreadProc wie ein callback immer wieder aufgerufen wird. ein thread stellt einen komplett parallelen ausführungspfad innerhalb des gleichen prozesses dar. deine ThreadProc dient als startfunktion in diesem pfad. CreateThread erstellt einen neuen thread für dich und dieser startet in deiner ThreadProc. der code in einem solchen thread wird (pseudo-) gleichzeitig mit dem code in den restlichen threads eines prozesses ausgeführt. wenn die ThreadProc returned (in C++ sollte man normal returnen und dinge wie ExitThread() nach möglichkeit nicht verwenden) ist der thread damit beendet. diese gleichzeitigkeit bringt einige lustige dinge mit sich (deadlocks, starvation, race conditions, ...) die das programmieren von derartigen anwendungen (nicht zwangsläufig, aber doch) zu einer ziemlich komplexen angelegenheit machen können.

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

34

22.01.2008, 15:52

uh.. ich habs in dem chaos mit den funktionspointern verschwitzt in der thread prozedur eine endlosschleife einzubauen.. folglich beendet die funktion auch ganz normal :D

sorry mein fehler.. ^^

hab nur vergessen:

C-/C++-Quelltext

1
2
3
4
while(bedingung)
{
    // ...

}



danke für die hilfe!
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

35

22.01.2008, 21:32

so jetzt reichts mir aber langsam mal..

also meine thread-proc ist nun static..

und ich hab gemerkt dass ich anscheinend keine funktion eines member-objektes darin aufrufen kann..

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// klassenmember

WinsockServer *pWinsockServer;

// -------------------------------------------------------------------

// Name:    frmServer_ServerThreadProc()

// Desc:    Thread procedure for the winsock server.

// -------------------------------------------------------------------

DWORD WINAPI frmServer::frmServer_ServerThreadProc (LPVOID lpPAram)
{
    int i = GetCurrentThreadId();

    
    while(1)
    {
        pWinsockServer->process();
    }
    

    return i;
} // frmServer_ServerThreadProc()


da meckert der compiler dass links von process() eine klasse/struktur/union stehn muss..

daklariere ich die funktion als NICHT static dann läuft das ganze wieder..

verrär mit jemand wie ich das bewerkstelligen kann?
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

36

22.01.2008, 21:39

Zitat von »"$nooc"«

und ich hab gemerkt dass ich anscheinend keine funktion eines member-objektes darin aufrufen kann..


ja das is deswegen so weil die funktion static ist. vielleicht solltest du dir mal anschaun was genau es mit static auf sich hat ;)

Zitat von »"$nooc"«

verrär mit jemand wie ich das bewerkstelligen kann?


so geht das auf jeden fall nicht. aber z.b. mit dem von mir zuvor geposteten ansatz über eine dummy ThreadProc, die intern eine methode eines objektes, das sie über ihren parameter bekommt, aufruft geht das...

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

37

22.01.2008, 21:55

omg.. naja das werd ich mir dann morgen ansehn.. bin saumüde und werd heute mal früher ins bett gehn ^^

danke für die hilfe :D
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

38

23.01.2008, 09:25

gibt es evtl. eine andere lösung zu der thematik?

wenn nicht..

kannst du mir dann erklären wie ich das machen kann?

also ich brauch ja einen funktionspointer mit der signatur wie LPTHREAD_START_ROUTINE .. und die übernimmt nur 1 parameter
(LPVOID lpParam)
ich hab die templates die du gepostet hast verstanden glaub ich, aber das würde dann ja nicht klappen wenn ich meine funktion dann CreateThread() übergebe oder? also wenn ich die parameterliste verändere..



*EDIT:

der 4te parameter CreateThread() ist laut msdn ein pointer auf eine übergebene variable.. in einem anderen forum hab ich gesehen wie jemand einen functor als parameter übergibt..

wäre es möglich einen functor zu schreiben, diesen dann als parameter zu übergeben, damit mein programm so läuft wie ich es gern hätte?


PSEUDO CODE

C-/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
// -------------------------------------------------------------------

// Name:    Create()

// Desc:    Creates a new thread.

// -------------------------------------------------------------------

template<typename T>
int Thread::Create(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, T* instance, LPVOID lpParameter, DWORD dwCreationFlags)
{
        // define function pointer

    DWORD (WINAPI *ThreadProc) (LPVOID) = &instance->frmServer_ThreadProc;

    if((m_hThreadHandle = CreateThread(lpThreadAttributes, dwStackSize, ThreadProc, lpParameter, dwCreationFlags, &m_dwThreadID)) == NULL)
        return THREAD_CREATING_ERROR;

    return THREAD_OK;
} // Create()



// functor: (einfach irgendwas)


template<typename T>
void functor(T object)
{
    object->process();
} 



// aufruf


Thread.Create(a, b, instanz, functor, e);



würde das so in etwas klappen?



EDIT:

ich glaub ich hab was ich brauche:

msdn:

C-/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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>

#define MAX_THREADS 3
#define BUF_SIZE 255

typedef struct MyData {
    int val1;
    int val2;
} MYDATA, *PMYDATA;

DWORD WINAPI MyThread( LPVOID lpParam ) 
{ 
    HANDLE hStdout;
    PMYDATA pData;

    TCHAR msgBuf[BUF_SIZE];
    size_t cchStringSize;
    DWORD dwChars;

    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    if( hStdout == INVALID_HANDLE_VALUE )
        return 1;

    // Cast the parameter to the correct data type.


    pData = (PMYDATA)lpParam;

    // Print the parameter values using thread-safe functions.


    StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"), 
        pData->val1, pData->val2); 
    StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
    WriteConsole(hStdout, msgBuf, cchStringSize, &dwChars, NULL);

    return 0; 
} 
 
int _tmain()
{
    PMYDATA pData;
    DWORD dwThreadId[MAX_THREADS];
    HANDLE hThread[MAX_THREADS]; 
    int i;

    // Create MAX_THREADS worker threads.


    for( i=0; i<MAX_THREADS; i++ )
    {
        // Allocate memory for thread data.


        pData = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
                sizeof(MYDATA));

        if( pData == NULL )
            ExitProcess(2);

        // Generate unique data for each thread.


        pData->val1 = i;
        pData->val2 = i+100;

        hThread[i] = CreateThread( 
            NULL,              // default security attributes

            0,                 // use default stack size  

            MyThread,          // thread function 

            pData,             // argument to thread function 

            0,                 // use default creation flags 

            &dwThreadId[i]);   // returns the thread identifier 



        // Check the return value for success.

        // If failure, close existing thread handles, 

        // free memory allocation, and exit. 


        if (hThread[i] == NULL) 
        {
           for(i=0; i<MAX_THREADS; i++)
           {
              if (hThread[i] != NULL)
              {
                 CloseHandle(hThread[i]);
              }
           }
           HeapFree(GetProcessHeap(), 0, pData);
           ExitProcess(i);
         }
    }

    // Wait until all threads have terminated.


    WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE);

    // Close all thread handles and free memory allocation.


    for(i=0; i<MAX_THREADS; i++)
    {
        CloseHandle(hThread[i]);
    }
    HeapFree(GetProcessHeap(), 0, pData);

    return 0;
}
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

39

23.01.2008, 15:37

Guck dir mal meinen Code an. Der hat das für dich alles bereits gemacht ... nungut. Der Trick besteht darin, dass man einem Thread beim starten "Userdata" übergeben kann. Wenn du außer einen this-Zeiger noch andere "Userdata" hast, nimmst du eine struct und sonst übergibst du einfach den this-Zeiger als "Userdata" bei CreateThread. Dann kannst du in der Klasse "Thread" erst eine static _thread_proc anlegen, die dann wiederrum, durch den übergebenen this-Zeiger eine nicht-static Funktion der Klasse "Thread", vorzugsweise thread_proc genannt, aufruft. Fertig! :)
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

40

23.01.2008, 15:46

deine lösung ist mir irgendwie zu komplex .. ^^ kann schon sein dass deine evtl. besser wäre, aber die simple variante einfach bei CreateThread() dem lpParam ein struct zu übergeben geht schneller über die bühne ohne viel um und auf :D

hoffe du bist nicht böse wenn ich die msdn-lösung übernehme ^^
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

Werbeanzeige