Newsgroup: it.comp.programmare.win32
Titolo: Richiamo di funzioni all'interno di multithreading

Ciao a tutti!
Ho da poco iniziato a programmare usando il multithreading.
Leggendo la documentazione contenuta nella MSDN ho visto che il
multithreading è applicabile a parti di codice rappresentate da funzioni
(infatti per creare un nuovo thread si deve passare alla CreateThread()
l'indirizzo della funzione da lanciare nel nuovo thread che stiamo creando).
Mi chiedevo cosa succederebbe se dopo aver lanciato un nuovo thread
richiamassi dall'interno di quest'ultimo una funzione appartenente ad
un'altra porzione programma.
Mi spiego meglio....
Il mio programma (una dll scritta in linguaggio C) contiene molte funzioni
tra cui FunzioneA(), una di esse (supponiamo che si chiami FunzioneX())
viene lanciata come nuovo thread. Se dall'interno di FunzioneX() richiamo
FunzioneA() cosa succede???
FunzioneA() viene eseguita come se appartenesse al thread avviato con
FunzioneX()???
Grazie a tutti (come sempre...)
Francesco

 FunzioneX()???
Si

Quasi dimenticavo...occhio a non intoppare :
Se dalla funzione che richiami dal thread effettui ad esempio delle
SendMessage (per esempio abiliti o disabiliti una finestra...) rischi di
toppare nel più classico dei problemi nell'utilizzo dei thread...
So che non lo avevi richiesto, ma dato che come da te specificato hai "da
poco iniziato a programmare usando il multithreading" mi sono sentito in
dovere di accennarti il problema...
Se non è il tuo caso amen, altrimenti se hai problemi o, come probabile, non
sono stato molto esauriente, non esitare...
Ma ciao

 Quasi dimenticavo...occhio a non intoppare :


 Quindi non ti lesinare nel darmi consigli.
Facciamo un esempio semplice semplice: mettiamo caso che nella classe della
tua finestra hai un puntatore ad un oggetto CWinThread (pThread) e che tu
abbia creato una funzione thread che in un modo o nell'altro va ad
aggiornare il testo del bottone, es:
UINT CBubbaDlg::MyThread(LPVOID Param)
{
    CBubbaDlg *pBubbaDlg = (CBubbaDlg *) Param;    //    Ottieni ad esempio
il puntatore alla finestra nel modo più classico
    int cont = 0;
    CString ButtonText;
    while(pBubbaDlg->CanDoWork())                        //    Mettiamo caso
ci sia una funzione che ci informa se è possibile nel calcolo
    {
            ButtonText.Format("%d", ++cont);
            pBubbaDlg->m_Button.SetWindowText(ButtonText);
    }
    return 0;
}
Dov'è l'intoppo? probabilmente ancora non si vede...
ovviamente bisogna stare attenti a bloccare il thread  prima che la finestra
(o meglio il bottone) venga distrutta, altrimenti come puoi immaginare
andrebbe in crisi tutto il baracchino...
quindi ci sarà una cosa di questo tipo :
void CBubbaDlg::OnDestroy()
{
 Syncronize();
 CBubbaDlg::OnDestroy();
}
Ora arriva il pezzo forte :
void CBubbaDlg::Syncronize()
{
 m_Suspend = TRUE;        //    Questo serve perchè ad esempio la famosa
funzione CanDoWork() restituisce ! m_Suspend
 if(m_pThread)
 {
    WaitForSingleObject(m_pThread->m_hThread, INFINITE);        //    Qui
rimane bloccato proprio all'infinito....
     m_pThread = NULL;
 }
 m_Suspend = FALSE;
}
Cosa succede? La cosa "strana" all'apparenza è che ogni tanto il programma
non si chiude mai e ogni tanto sembra non avere problemi...
Finalmente arriviamo alla famosa spiegazione...
Il problema è che la WaitForSingleObject aspetta finchè il thread non
termina, nel nostro caso fino all'istruzione "return 0;", ma mettiamoci in
questo caso :
nella funzione MtThread siamo arrivati all'istruzione
"ButtonText.Format("%d", ++cont);" a questo punto la "Syncronize" richiama
"WaitForSingleObject", l'istruzione successiva di "MyThread" è
"pBubbaDlg->m_Button.SetWindowText(ButtonText);" che in realtà è un wrapper
alla funzione SendMessage (che è sincrona...) con gli opportuni paramentri e
qui si spiega come mai il programma non si chiude: i due thread si
"aspettano" a vicenda, quindi il programma non si chiude.
Il motivo per cui non è sempre detto che il programma si blocchi è che può
capitare di avere una situazione di questo tipo: il thread esegue
"pBubbaDlg->m_Button.SetWindowText(ButtonText);" subito dopo viene
richiamato da "Syncronize" "WaitForSingleObject", a questo punto il
"MyThread" richiama "CanDoWork" che restituisce FALSE e tutti vissero felici
e contenti...
Le soluzioni possono essere molte, la più semplice (anche se io non uso
questa per una questione di comodità...) è stare attenti ad usare
PostMessage (che al contrario di SendMessage è asincrona).
Spero che da tutto questo casino si sia riuscito a cogliere il succo del
discorso, chiedo inoltre scusa per non avere dato molto peso alla
grammatica...
Ma riciao !