robrock80 (Normal User)
Pro
Messaggi: 143
Iscritto: 11/12/2006
|
Salve a tutti. Ho scritto 2 funzioncine per inviare MessageBox, ma non funzionano, probabilmente uso male i mutex, ecco il codice
Codice sorgente - presumibilmente C# |
typedef struct _Params { void *param[11]; void *returned[11]; void (*function[11])(struct _Params *); } Params; HANDLE sendAsynchronousMessage(TCHAR title[], TCHAR text[], int type) { DWORD dwThreadId; HANDLE mutex = CreateMutex(NULL,FALSE,NULL); Params params = {{(TCHAR*)title,(TCHAR*)text, &type, &mutex}}; HANDLE hThread = CreateThread( NULL, //Choose default security 0, //Default stack size (LPTHREAD_START_ROUTINE)&sendMessage, ¶ms, 0, //Lancia il Thread immediatamente &dwThreadId); WaitForSingleObject(mutex, INFINITE); printf("mutex rilasciato\n"); return hThread; } DWORD sendMessage(LPVOID param) { Params* params = (Params*)param; HANDLE mutex = (HANDLE*)params->param[3]; TCHAR * title = (TCHAR *)malloc (sizeof(TCHAR ) * _tcslen ((TCHAR *)params ->param [0 ])); _tcscpy(title,(TCHAR*)params->param[0]); TCHAR * message = (TCHAR *)malloc (sizeof(TCHAR ) * _tcslen ((TCHAR *)params ->param [1 ])); _tcscpy(message,(TCHAR*)params->param[1]); if (mutex != 0) { printf("entrato\n"); ReleaseMutex(mutex); } MessageBox( NULL, message, title, *(int*)params->param[2]); free(title); free(message); return 0; }
|
Praticamente mi salta il wait del mutex, dove sbaglio?
Ultima modifica effettuata da robrock80 il 25/03/2010 alle 16:02 |
|
TheKaneB (Member)
Guru^2
Messaggi: 1792
Iscritto: 26/06/2009
|
il mutex lo devi rilasciare DOPO che l'utente ha chiuso la MessageBox, altrimenti lo rilascia così rapidamente che la wait dura pochi nanosecondi...
|
|
robrock80 (Normal User)
Pro
Messaggi: 143
Iscritto: 11/12/2006
|
Aspetta... vedi i 2 printf?
Mi stampa praticamente prima "rilasciato" e poi "entrato", mentre io mi aspetto che quando arriva alla wait il programma si ferma in attesa della release, invece non aspetta la release e va avanti
Ultima modifica effettuata da robrock80 il 25/03/2010 alle 16:03 |
|
TheKaneB (Member)
Guru^2
Messaggi: 1792
Iscritto: 26/06/2009
|
l'ordine dei printf non è affidabile. Vengono bufferizzati dalla console in modo del tutto asincrono. Puoi forzare la scrittura mettendo un fflush() dopo ogni printf(), ma questo interviene solo sul secondo livello di bufferizzazione (quello del VFS del kernel, che tratta lo standard output come un vero e proprio file), quindi non è garantito nemmeno in questo caso l'ordinamento corretto delle stringhe...
|
|
robrock80 (Normal User)
Pro
Messaggi: 143
Iscritto: 11/12/2006
|
Ma c'è un modo sicuro per stampare in maniera sincronizzata?
Ultima modifica effettuata da robrock80 il 25/03/2010 alle 16:27 |
|
TheKaneB (Member)
Guru^2
Messaggi: 1792
Iscritto: 26/06/2009
|
quando si entra nel campo del multithreading, la sincronizzazione diventa un argomento difficile da trattare.
Se usi una console normale (con il normale printf) devi accollarti l'incertezza dell'ordine di arrivo. L'ordine è garantito solo all'interno dello stesso thread.
Questo è un limite intrinseco.
Probabilmente esistono versioni "sicure" e sincronizzate di printf, ma devi consultare approfonditamente le API di windows per fare questo, perchè il C standard non contempla nemmeno l'esistenza dei thread e delle primitive di sincronizzazione...
Non conosco approfonditamente windows, quindi lascio ad altri la palla :P
|
|
robrock80 (Normal User)
Pro
Messaggi: 143
Iscritto: 11/12/2006
|
Comunque, qui non è un problema di printf, perchè ho provato a sostituire la wait con lo Sleep(1000) e il programma funziona. Tra l'altro non posso mettere la Release dopo MessageBox altrimenti perdo il multithread perchè quando lancio MessageBox il processo attende l'input dell'utente. Mi chiedo a questo punto se ho usato bene il mutex
|
|
TheKaneB (Member)
Guru^2
Messaggi: 1792
Iscritto: 26/06/2009
|
ok, allora...
dal momento che il mutex serve per "proteggere" delle risorse condivise (immagino nel tuo caso siano title e message), il suo uso corretto è questo:
threadA:
wait(mutex)
// uso le variabili condivise
release(mutex)
threadB:
wait(mutex)
// uso ...
release(mutex)
entrambi devono chiamare la wait, ed entrambi la release.
La prima wait passa liscia, la seconda viene bloccata (solo un oggetto alla volta può accedere, quindi la prima wait passa indisturbata).
Appena il primo thread chiama la release, la seconda wait viene sbloccata.
ricorda: la prima wait passa SEMPRE liscia. Tutte le successive vengono bloccate (finchè non arriva una release).
Quindi modifica il tuo codice in modo da strutturarlo nel modo che ti ho schematizzato...
attualmente usi in modo scorretto la protezione della risorsa condivisa (c'è solo una wait, che passerà quindi indisturbata).
Ultima modifica effettuata da TheKaneB il 25/03/2010 alle 16:45 |
|
robrock80 (Normal User)
Pro
Messaggi: 143
Iscritto: 11/12/2006
|
Ho risolto in un'altra maniera: ho utilizzato un evento al posto del mutex, ma a questo punto mi riamene un dubbio: ma la wait sul mutex ha effetto solo sui thread creati con CreateThread o funziona anche per il thread principale del processo?
|
|