Oppure

Loading
25/03/10 14:42
robrock80
Salve a tutti. Ho scritto 2 funzioncine per inviare MessageBox, ma non funzionano, probabilmente uso male i mutex, ecco il codice

	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,
					&params,
					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 25/03/10 15:02
aaa
25/03/10 14:56
TheKaneB
il mutex lo devi rilasciare DOPO che l'utente ha chiuso la MessageBox, altrimenti lo rilascia così rapidamente che la wait dura pochi nanosecondi...
aaa
25/03/10 15:01
robrock80
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 25/03/10 15:03
aaa
25/03/10 15:21
TheKaneB
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...
aaa
25/03/10 15:27
robrock80
Ma c'è un modo sicuro per stampare in maniera sincronizzata?
Ultima modifica effettuata da robrock80 25/03/10 15:27
aaa
25/03/10 15:33
TheKaneB
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
aaa
25/03/10 15:37
robrock80
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
aaa
25/03/10 15:45
TheKaneB
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 25/03/10 15:45
aaa