Priklad na urovni operacniho systemu - vytvoreni noveho vlakna a vyuziti synchronizace – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Priklad na urovni operacniho systemu - vytvoreni noveho vlakna a vyuziti synchronizace – C / C++ – Fórum – Programujte.comPriklad na urovni operacniho systemu - vytvoreni noveho vlakna a vyuziti synchronizace – C / C++ – Fórum – Programujte.com

 

BigBear0
Stálý člen
10. 1. 2010   #1
-
0
-

Ahojte, vypracoval jsem priklad a nefunguje tak, jak ma... zadani je na pocatku zdrojoveho kodu:

#include <stdio.h>

#include <stdlib.h>
#include <windows.h>
#include <time.h>

/**********************************************
ZADANI:
Napište program, ve kterém vytvoříte vlákno.
Toto vlákno bude monitorovat stav objektu
události a při signalizovaném stavu se ukončí.
Objekt signalizujte z prvního vlákna.
**********************************************/

/* Obsluha chybovych hlaseni */
void ErrorExit (LPTSTR lpszMessage) {
fprintf(stderr, "%s\n", lpszMessage);
ExitProcess(0);
}

/* funkce predavana novemu vlaknu */
void ThreadFunction(LPVOID lpParam)
{
printf("-----------------------------------\n");
printf("\nvlakno bylo vytvoreno\n\n");
printf("-----------------------------------\n");

HANDLE hEvent; // handle udalosti
hEvent = (HANDLE) lpParam; // udalost zpristupnena ve vlaknu

DWORD dwWaitResult; // vysledek cekaci funkce

dwWaitResult = WaitForSingleObject(
hEvent, // handle udalosti (objektu)
INFINITE); // doba cekani

if (dwWaitResult == WAIT_OBJECT_0)
{
printf("\nvlakno bylo signalizovano\n");
} else if (dwWaitResult == WAIT_FAILED) {
ErrorExit("Funkce WaitForSingleObject selhala.\n");
}

if (!ResetEvent(hEvent)) // nastavi udalost zpet do nesignalizovaneho stavu
{
ErrorExit("Nezdarilo se nastavit udalost do nesignalizovaneho stavu.\n");
}
printf("\n... vlakno bylo ukonceno\n");
ExitThread(0); // ukonci vlakno s navratovym kodem 0
}

/* vytvori objekt udalosti a vlakno, kde bude udalost zpristupnena a signalizuje udalost */
void createObjectsAndSignalizeEvent()
{
HANDLE hEvent; // handle udalosti

// vytvoreni udalosti
hEvent = CreateEvent(
NULL, // ukazatel na strukturu SECURITY_ATTRIBUTES
TRUE, // typ objektu manual-reset
FALSE, // pocatecni stav nesignalizovan
"MonitoredEvent"); // jmeno objektu udalosti

if (hEvent == NULL) { // jestlize vrati CreateEvent NULL
ErrorExit("Funkce CreateEvent selhala.\n");
}

HANDLE hThread; // handle vlakna
DWORD dwThreadId; // identifikator vlakna

// vytvoreni vlakna
hThread = CreateThread(
NULL, // struktura ochrannych parametru - NULL
0, // inicializace velikosti zasobniku - 0 = default size
(LPTHREAD_START_ROUTINE)ThreadFunction, // funkce, kterou vlakno spusti
&hEvent, // parametr dane funkce - zpristupni udalost
0, // priznak ovladajici vytvoreni vlakna - 0 = vlakno se spusti ihned po vytvoreni
&dwThreadId); // promenna, do ktere se ulozi identifikator vlakna
if (hThread == NULL) // jestlize se vlakno nepodari vytvorit, vrati CreateThread NULL
{
ErrorExit("Nepodarilo se vytvorit vlakno.\n");
}

// generuje nahodna cisla v cyklu a pokazde vypise hlasku... az vygeneruje cislo 9, tak signalizuje objekt
srand((unsigned int)time(NULL));// inicializuje generator nahodnych cisel
while ((rand() % 20) != 9) // ceka dokud nahodne cislo do 20 neni rovno 9
{
printf("udalost je stale v nesignalizovanem stavu...\n");
}
printf("\nudalost nastavuji do signalizovaneho stavu...\n");
if (!SetEvent(hEvent))
{
ErrorExit("Nezdarilo se nastavit udalost do signalizovaneho stavu.\n");
}
}

void main()
{
createObjectsAndSignalizeEvent();
printf("\n");
}
po prelozeni je vse vporadku, spustim-li program, rozbehne se, ale rozbehne se asi jen funkce createObjectsAndSignalizeEvent(), protoze se na std vystup vypise parkrat "udalost je stale v nesignalizovanem stavu..." a na konci "udalost nastavuji do signalizovaneho stavu..." a ja bych cekal, ze se nekde mezi tim vypise

-----------------------------------

vlakno bylo vytvoreno

-----------------------------------

vlakno bylo signalizovano

... vlakno bylo ukonceno

a ono se tak nestane :-(... nevite, co mam spatne? Mohli byste mi to, prosim nekdo vysvetlit? Mockrat dekuji :-)

Nahlásit jako SPAM
IP: 88.103.186.–
NECIN DRUHYM TO, CO NECHCES, ABY ONI CINILI TOBE!
Jura
~ Anonymní uživatel
637 příspěvků
10. 1. 2010   #2
-
0
-

Zdravim,

v tvem kodu vidim par chyb:
1) hlavicka funkce neodpovida predpisu hlavicce, kterou by mela mit(ma vracet cislo)
2) nikde neuvolnujes prostredky(sice to uvolni system po ukonceni aplikace, ale takhle je to cesta do pekel)

tady je muj priklad pro inspiraci(snad to bude bez chyb:)):



#include <stdio.h>
#include <windows.h>

typedef struct _ThreadInfo
{
DWORD dwThreadID;
HANDLE hThread;
} ThreadInfo;

typedef struct _BigBearThreadData {

ThreadInfo info;
HANDLE hEvent;

} BigBearThreadData;


BigBearThreadData g_data = {0};

static DWORD WINAPI BigBearThreadProc(LPVOID lParam)
{
BigBearThreadData* pData= (BigBearThreadData*)lParam;
if( NULL != pData->hEvent ) {
// pockame na udalost, snad se nekdy dockame
const DWORD dwWaitResult = WaitForSingleObject(pData->hEvent, INFINITE);
if( WAIT_OBJECT_0 == dwWaitResult ) {
printf("Tak jsme se dockali\n");
}
else {
fprintf(stderr, "Neco se posralo pri cekani...");
}
}
printf("Vlakno konci\n");
return 0;
}

static void BigBearTest()
{
g_data.info.hThread
= CreateThread(NULL, 0, BigBearThreadProc, &g_data, 0, &g_data.info.dwThreadID);
g_data.hEvent
= CreateEvent(NULL, FALSE, FALSE, NULL);
if( NULL != g_data.info.hThread && NULL != g_data.hEvent ) {
// pockame cca 5 vterin
Sleep(5000);
// odpalime udalost
SetEvent(g_data.hEvent);
// pockame az vlakno dodela svoji praci
WaitForSingleObject(g_data.info.hThread, INFINITE);
}
// uklidime udalost
if( NULL != g_data.hEvent )
CloseHandle(g_data.hEvent);
// uklidime vlakno
if( NULL != g_data.info.hThread )
CloseHandle(g_data.info.hThread);
}

int main(int argc, char* argv[])
{
BigBearTest();
return 0;
}

Nahlásit jako SPAM
IP: 85.207.192.–
BigBear0
Stálý člen
11. 1. 2010   #3
-
0
-

Ahoj, perfektni, po upravach mi tedy funguje i muj kod... vytvoril jsem si dane struktury, ale nepouzil jsem globalni promennou g_data a misto ni jsem si v obou funkcich vytvoril lokalni promenne typu BigBearThreadData... neco ale nechapu... chtel bych se te na to tedy zeptat... proc nefunguje kod po takoveto uprave?

#include <stdio.h>

#include <windows.h>

static DWORD WINAPI BigBearThreadProc(LPVOID lParam)
{
HANDLE hEvent = (HANDLE)lParam;

if( NULL != hEvent ) {
// pockame na udalost, snad se nekdy dockame
const DWORD dwWaitResult = WaitForSingleObject(hEvent, INFINITE);

if( WAIT_OBJECT_0 == dwWaitResult ) {
printf("Tak jsme se dockali\n");
}
else {
fprintf(stderr, "Neco se posralo pri cekani...\n");
}
}

printf("Vlakno konci\n");

return 0;
}

static void BigBearTest()
{
DWORD dwThreadID;
HANDLE hThread, hEvent;

hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
hThread = CreateThread(NULL, 0, BigBearThreadProc, &hEvent, 0, &dwThreadID);

if ( NULL != hThread && NULL != hEvent ) {
// pockame cca 5 vterin
Sleep(5000);
// odpalime udalost
SetEvent(hEvent);
// pockame az vlakno dodela svoji praci
WaitForSingleObject(hThread, INFINITE);
}

// uklidime udalost
if( NULL != hEvent )
CloseHandle(hEvent);

// uklidime vlakno
if( NULL != hThread )
CloseHandle(hThread);
}

int main(int argc, char* argv[])
{
BigBearTest();
return 0;
}
Myslel jsem, ze jestli vytvorim datovou strukturu, ktera vlastne obsahuje HANDLE hEvent, HANDLE hThread a DWORD dwThreadID, nebo si primo vytvorim tyto tri promenne, tak to bude fungovat stejne, az na to, ze to bude hure citelne... a to jsem udelal a novemu vlaknu jsem jako parametr poslal primo tu udalost a pak ji obslouzil... proc to tedy nefunguje? Mockrat dekuji :-)

Nahlásit jako SPAM
IP: 94.74.255.–
NECIN DRUHYM TO, CO NECHCES, ABY ONI CINILI TOBE!
Jura
~ Anonymní uživatel
637 příspěvků
11. 1. 2010   #4
-
0
-

Cau,

problem je ve volani funkce CreateThread a predani parametru hEvent. Jde o to, ze ty predavas adresu handle te eventy, jenze musis si uvedomit, ze promenna hEvent uz jako hodnotu obsahuje adresu, se kterou chces pracovat - to je vyznam HANDLE, je to vlastne ukazatel(mel by to byt typedef na void*). Takze kdyz to vytvoreni vlakna zavolas takto:



hThread = CreateThread(NULL,
0,
BigBearThreadProc,
hEvent, /*tady nepatri ampersand*/
0,
&dwThreadID);

Jeste k tem lokalnim promennym: Dej si pozor na jejich platnost, protoze kdyby jsi necekal na ukonceni pracovniho vlakna, tak by jsi ztratil odkazy na handle vlakna i eventy a uz bys je nemohl uvolnit.

Nahlásit jako SPAM
IP: 85.207.192.–
BigBear0
Stálý člen
11. 1. 2010   #5
-
0
-

Chapu, mockrat dik :-)

Nahlásit jako SPAM
IP: 94.74.255.–
NECIN DRUHYM TO, CO NECHCES, ABY ONI CINILI TOBE!
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 20 hostů

Podobná vlákna

Buffer operačního systému — založil Matěj Andrle

Vlákna - synchronizace — založil johny

Vlákna - synchronizace — založil crazy

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý