PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : CreateThread in VC++



phoku
11-06-2004, 10:43
Hallo,

ich habe in meinem Programm nen Aufruf
Aktion = MitSpieler[0].machZug();

Da die Methode etwas rechenintensiv ist, liegt solange die GUI still. Wie kann ich für den Aufruf einen neuen Thread erzeugen?

Mein Problem ist vor allem der RETURN-Wert von der Funktion.

thx
phoku

TThomas
11-06-2004, 12:55
HANDLE mutx;
Aktion my_Aktion = NULL;


DWORD WINAPI my_thread(void *par)
{
//
// HIER DEINEN CODE
//

// alles berechnet, Rueckgabewert setzten

WaitForSingleObject (mutx, 1000);
my_Aktion = mein_rueckgabe_wert;
ReleaseMutex (mutx);

return 0;
}


int main ()
{
HANDLE threadHandle;
DWORD threadId = 0;


//
// HIER DEINEN CODE
//

// Mutex erzeugen
mutx = CreateMutex (NULL, false, NULL);

// Tread erzeugen
threadHandle = CreateThread (0, 0x1000, &my_thread, 0, 0, &threadId);

//
// FOO BAR (irgendwas anderes machen...)
//

// jetzt sollte alles berechnet sein, ueberpruefen...
// falls Berechnung noch nicht fertig: warten
for (;;)
{
WaitForSingleObject (mutx, 1000);
if (my_Aktion != NULL)
{
ReleaseMutex (mutx);
break;
}
ReleaseMutex (mutx);
Sleep (10);
}

//
// MEHR VON DEINEM CODE
//

return 0;
}




Ganz simpel mit einem Mutex, Fehler werden hier nicht abgefangen.

TThomas
11-06-2004, 13:14
Ich habe eben erst gesehen dass du das ganze in eine GUI packen willst.

Das ist wesentlich komplizierter, da du der CreateThread-Funktion keine Memberfunktionen übergeben darfst.

Um die Methode einer Klasse als Thread laufen zu lassen, musst du eine Funktion ausserhalb der Klasse schreiben, welche als Übergabeparameter einen Funktions-Pointer auf die Member-Klasse hat, die Funktion ruft die CreateThread-Funktion mit dem übergebenen Funktionspointer auf. In der Klasse selbst rufst du dann die externe Funktion mit dem Pointer auf die Klassenmethode auf.

Sehr unschön, aber was will man machen...


Thomas.

anda_skoa
11-06-2004, 13:41
Hab bei Google einige CThread Implementierungen gefunden, also eine Art Threadklasse für MFC, falls du das benutzt.

Ciao,
_

phoku
11-06-2004, 23:08
Hallo, hab das jetzt wie folgt:


HANDLE mutx;
Spieleraktion my_Aktion;
int warten;
void prePareNegamax(int thisfeld[SIZE][SIZE])
{...};

DWORD WINAPI my_thread(void *par)
{
prePareNegamax(par);

WaitForSingleObject (mutx, 1000);
warten = 0;
ReleaseMutex (mutx);

return 0;
}

Spieleraktion machZug(int thisfeld[SIZE][SIZE])
{
HANDLE threadHandle;
DWORD threadId = 0;
warten=1;

//
// HIER DEINEN CODE
//

// Mutex erzeugen
mutx = CreateMutex (NULL, false, NULL);

// Tread erzeugen
threadHandle = CreateThread (0, 0x1000, &my_thread, thisfeld, 0, &threadId);

//
// FOO BAR (irgendwas anderes machen...)
//

// jetzt sollte alles berechnet sein, ueberpruefen...
// falls Berechnung noch nicht fertig: warten
for (;;)
{
WaitForSingleObject (mutx, 1000);
if (!warten)
{
ReleaseMutex (mutx);
break;
}
ReleaseMutex (mutx);
Sleep (10);
}
return my_Aktion ;
}




bekomme aber Fehlermeldungen:
error C2664: 'ComputerSpieler::prePareNegamax' : cannot convert parameter 1 from 'void *' to 'int [][15]'
error C2276: '&' : illegal operation on bound member function expression

TThomas
11-06-2004, 23:22
DWORD WINAPI my_thread(void *par)
Du kannst als Parameter also nur einen void-Pointer übergeben.

Entweder du castest dein Array nach "void *" oder zu kopierst das Array in eine globale Variable um, auf welche der Thread zugreifen kann, um auf den Übergabeparameter zu verzichten.

phoku
12-06-2004, 12:38
okay, wenn ich

threadHandle = CreateThread(NULL,0,ThreadMain,NULL,0,&threadId);
mache gibt er mir aber dann die Fehlermeldung
C2664: 'CreateThread' : cannot convert parameter 3 from 'void (void)' to 'LPTHREAD_START_ROUTINE'

ein & vor ThreadMain nimmt er sowiso nicht

TThomas
12-06-2004, 12:57
Ich habe hier jetzt kein Windows, daher alles aus dem Gedächtnis...


threadHandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Thread Main,NULL,0,&threadId);


Sieht logisch aus, oder? ;)

phoku
12-06-2004, 13:00
klar, sieht logisch aus. hab ich auch schon versucht, aber dann kommt:
error C2440: 'type cast' : cannot convert from 'overloaded-function' to 'LPTHREAD_START_ROUTINE'
:(

TThomas
12-06-2004, 13:09
DWORD WINAPI thread( PVOID par )
{
// WHATEVER
return 0;
}


int main( int argc, char *argv[])
{
// VARIABLEN ETC

threadHandle = CreateThread(0,0x1000,thread,0,0,&threadId);
SetThreadPriority(threadHandle,THREAD_PRIORITY_TIM E_CRITICAL);

// FOO BAR
}


Habe ich eben aus was altem auf meiner Platte rausgekramt, ich kann nur wie gesagt nicht testen, ob alles glatt läuft. Müsste aber!

phoku
12-06-2004, 16:34
ne, da krieg ich die gleiche Fehlermeldung:
error C2664: 'CreateThread' : cannot convert parameter 3 from 'DWORD (PVOID)' to 'LPTHREAD_START_ROUTINE'

TThomas
14-06-2004, 09:33
#include <windows.h>
#include <iostream>

DWORD WINAPI thread (PVOID par)
{
for (int i = 0; i < 999; i++)
{
std::cout << "THREAD" << std::endl;
Sleep (1);
}


return 0;
}


int main (int argc, char *argv[])
{
HANDLE threadHandle;
unsigned long threadId;

threadHandle = CreateThread(0,0x1000,thread,0,0,&threadId);


for (int i = 0; i < 999; i++)
{
std::cout << "MAIN" << std::endl;
Sleep (1);
}


return 0;
}



Ich habe das eben bei der Arbeit geschrieben und es compiliert ohne Probleme.
Ich habe das Visual Studio 6 benutzt.


Thomas.