Newsgroup: it.comp.lang.c++
Titolo: Ma è un thread o NO ?

Sto "giocando" un po' con le classi MFC e in + precisamente con la
CWinThread.
Il mio tentativo è quello di fare eseguire una finestra dialogo (figlia)
dentro un'altra finestra dialogo (padre) in multy-thread.
Vi faccio un esempio :
class MioDialogo : public CDialog
{
    int ProceduraCheContaIGranelliDiSabbiaDellaCostaMediterranea()
    .......costruttore,distruttore, ecc
};
int MioDialogo ::ProceduraCheContaIGranelliDiSabbiaDellaCostaMediterranea()
{
......
}
class MioThread : public CWinThread
{
    .......costruttore,distruttore, ecc
};
BOOL MioThread:InitInstance
{
    m_pMainWnd = new MioDialogo(NULL /*Parent*/ );  //il costruttore chiama
anche Create(..)
    m_pMainWnd->ShowWindow(SW_SHOW);
    m_pMainWnd->UpdateWindow();
    return TRUE;
}
e poi il solito :
.......
afxBeginThread( RUNTIME_CLASS(MioThread) );
...
Tutto come da manuale.
Il fatto è che la cosa funziona, ma appebna viene chiamata la funzione :
"ProceduraCheContaIGranelliDiSabbiaDellaCostaMediterranea()"
tutta l'applicazione si inchioda, aspettando che la funzione finisca;
WHY ???, non doveva essere multy-thread ??
Lo so che è una domanda difficile;
...ma quando il gioco si fa duro... sono i duri che giocano ;-)

...

Da quanto ho capito la situazione dovrebbe essere questa:
Tu hai un'applicazione (con un suo tread).
Ad un certo punto viene creato un altro thread, che a sua volta crea un
finestra.
la finestra esegue un'operazione abbastanza lunga:
(ProceduraCheContaIGranelliDiSabbiaDellaCostaMediterranea).
L'operazione però viene effettuata nello stesso thread della finestra,
che quindi, essendo impegnata a eseguire l'operazione di cui sopra,
non potrà fare altri lavori, come rispondere di tanto in tanto al
messaggio WM_PAINT, o agli eventi del mouse o di tastiera.
Se tu hai una finestra principale per l'applicazione noterai che
questa, invece, funziona correttamente.
Dovresti creare invece un working thread, cioè una funzione che
*gira* su un altro thread, e lasciare che la tua dialog giri nello
stesso thread dell'applicazione.
L'operazione può essere molto semplice, se la funzione non interagisce
con la dialog. Altrimenti devi prestare attenzione alla sincronizzazione dei
due thread. Ti consiglio un'ottima lettura in proposito:
"Programmazione avanzata in Windows" di Jeffrey Richter edito dalla
Mondadori Informatica. La traduzione è molto buona.
Ciao,
    Oreste Notelli


[sorry per aver troncato qui il messaggio ma il mio server č piuttosto
"intollerante" con i reply troppo quotati]
Premetto che non conosco approfonditamente MFC prendi la mia risposta con
"beneficio di inventario".
In windows32 la gestione delle finestre si appoggia sulla gestione dei
messaggi ad esse associati:
nel caso piů comune (message loop "classico"):
while (!GetMessage(...))
{
    TranslateMessage(...
    DispatchMessage(...
}
Attraverso le funzioni sopracitate (o altre tipo PeekMessage), i messaggi
vengono prelevati da una coda e inviati alla finestra di destinazione;
l'unica eccezione č il messaggio di quit (generato dalla PostQuitMessage())
che, generalmente, causa l'uscita dal loop dei messaggi (e la chiusura
dell'applicazione).
Esiste una coda di messaggi per ogni thread; i messaggi relativi ad una
finestra vengono postati nella coda del thread in cui la finestra (o dialog)
č stata creata.
Normalmente le applicazioni utilizzano un loop dei messaggi nel thread
principale del processo (WinMain) e creano altri thread che non
interagiscono con l'utente per le operazioni che richiedono parecchio tempo
per essere completate.
Nel tuo caso dovresti prima creare la Dialog box e poi creare il thread che
richiama la funzione
ProceduraCheContaIGranelliDiSabbiaDellaCostaMediterranea (anche se il nome
della costa dovresti passarglielo come parametro :-) ).
Al termine dell'esecuzione del thread suddetto dovresti postare un messaggio
che provochi la chiusura della dialog box.
---
Valter Minute
min...@fortech.it
 (the reply address of this message is invalid)
---
Are you looking for a good freeware ScreenSaver? Try FOYD!
http://hotfiles.zdnet.com/cgi-bin/texis/swlib/hotfiles/getit.bin?fcode=000PZ
0
if you want, I can send you the (free) C++ source code.

questa, invece, funziona correttamente.
E' questo il punto, sono d'accordo che la finestra del nuovo thread rimanga
inchiodata durante la funzione
"ProceduraCheContaIGranelliDiSabbiaDellaCosta( CString NomeCosta ;-)"
ma il fatto è che rimane inchiodata anche la finesta principale, e la cosa
non mi convince.
Quindi, che senso ha creare un UI (User Interface) thread, se questo mi
inchioda anche la finestra principale ?
Forse, sarà perché  ho definito il secondo dialogo come CHILD e anche se è
di un processo diverso,  interagisce sempre con il dialogo "padre" !!
Attualmente, infatti, sono stato costretto ad usare il working-thread (per
ovviare al blocco);
L' UI thread mi era comodo per la possibilita di gestire gli "WM_USER"
MESSAGE in ricezione, cosa che con il Wrk-th non è possibile fare
sempèlicemente (occorre l'handle di una window).
Se ti viene qualcosa in mente fammi un beep.
Saluti.

Walter, grazie 1024 per il tuo aiuto.
Supponevo che le due finestra hanno una gestione della coda dei messaggi
indipendente,
ma il fatto è che questo non accade.
Sara perché il secondo dialogo (thread) è CHILD o ho combinato qualche
missilata ?
Saluti .

...

Il dialog viene creato all'interno di un thread diverso da quello della
finestra principale, quindi possiede una sua coda dei messaggi ma il suo
message loop è bloccato fino a quando non termina l'esecuzione della tua
funzione.
Se il dialog è child della finestra principale è possibile che si verifichi
un deadlock tra le due code (la finestra principale sta cercando di inviare
un messaggio alla dialog (con SendMessage) ma il message loop di
quest'ultima è troppo impegnato a contare i granelli di sabbia :-)


quest'ultima è troppo impegnato a contare i granelli di sabbia :-)
Sai che ti dico,
rifaccio il tutto a mente serena (senza DS_CHILD) e vi faccio sapere.
Saluti.
Amos.