Newsgroup: it.comp.programmare.win32
Titolo: aiuto a chi ha piu' esperienza

ciao, volevo ascoltare il parere ( e ne ho veramente bisogno ) da chi ha
piu' esperienza di me nella programmazione nel multithreading...
premetto che mi sto leggendo il libro del Ritcher, "programmare applicazioni
per windows" ( stupendo!!! ) e in base a quello ho pensato l'architettura
del programma che devo sviluppare al lavoro, il problema e ' che non ho
esperienza in questo campo, sto da solo come un cane,  e non vorrei che cio'
che ho scelto sulla carta poi non funzioni in pratica, e per questo vorrei
il vostro consiglio...
ho creato una classe Serial che mi scrive/legge sulla porta seriale, e
contiene, tra le tante,  due funzioni membro:
una che mi fa continuamente polling sulla seriale gia' dall'avvio del
programma, in pratica mi invia un pacchetto, scritto sul protocollo che
adotta il committente del programma, e mi attende la risposta, questo e' un
loop infinito e l'ho implementato come thread all'avvio del programma (
static DWORD WINAPI MakePolling (LPVOID lpMyArg)... )
a un certo punto l'utente, navigando tra le dodici dialog che ho creato,
preme un pulsante qualsiasi e qui parte l'altra procedura della mia classe
(  static DWORD WINAPI DispatchMsg ((LPVOID lpMyArg)... )...
il fatto e' che quando l'utente preme quel pulsante il thread del polling
deve: primo stopparsi e secondo non deve aver "sporcato" il buffer di
trasmissione, altrimenti questo secondo thread, oltre ad inviare il
pacchetto suo, inviera' anche i bytes accodati che erano stati intanto
scritti sul buffer di tx dalla MakePolling, secondo: deve ripartire dopo che
il secondo thread ha esaurito il suo compito.
Premetto che nel secondo thread, ho utilizzato per sincronizzare piu'
pacchetti messi in coda, l'oggetto critical_section, che cosi' mi schedula i
vari thread derivanti dagli n pulsanti premuti consecutivamente.
Ora l'oggetto CRITICAL_SECTION funziona egregiamente, ma ci sono dei dubbi
che non riesco a risolvere...
Ho seguito il consiglio di Walter Minute e Porlock ( a proposito, grazie ) e
mi sto studiando la gestione della CreteEvent, Wait ForSingleObject... , ma
non capisco SE e COME devo utilizzarli nel mio programma...
Il problema e' questo: nel thread MakePolling ho scritto questo:
for ( ; ; )
{
    // scrivo e invio il pacchetto
    // sleep (100)
    // leggo il pacchetto di risposta dalla ricetrasmittente
    // aspetto 300 millisecondi e poi riparto con thread, fino all'infinito
    // sleep (300)
}
ho provato a implementare la CreateEvent e la SetEvent ma il problema e'
questo, se io lo metto all'inizio del for
es.
for ( ; ; )
{
    WaitForSingleObject (myHandle, INFINITE);
    // scrivo e invio il pacchetto
    // sleep (100)
    // leggo il pacchetto di risposta dalla ricetrasmittente
    // aspetto 300 millisecondi e poi riparto con thread, fino all'infinito
    // sleep (300)
}
e nella DispatchMsg come prima cosa creo l'evento, puo' succedere che questo
si crei quando sto gia' a meta' procedura nella MakePolling , quindi il
buffer di TX e' sporco,e parte immediatamente il mio secondo thread
DispatchMsg...
succede allora che la ricetrasmittente riceve un pacchetto sconosciuto e non
mi risponde correttamente...
allora ho adottato questa soluzione: l'handle che mi crea il thread Polling
( hPolling ) e' statico e pubblico e quindi all'avvio
della DispatchMsg, prima ancora di utilizzare la EnterCriticalSection ( &
miaStruttura), ho scritto:
for ( ; ; )
{
    if (hPolling != INVALID_HANDLE_VALUE)
    {
        TerminateThread(hPolling, 0);
        CloseHandle(hPolling);
        hPolling = INVALID_HANDLE_VALUE;
    }
   EnterCriticalSection(...)...
   // processo le mie istruzioni per l'invio/ricezione del pacchetto
   // e poi ricreo il thread polling
   LeaveCriticalSection(...)...
   hPolling = CreateThread (... MakePolling...)
}
Quattro domande ( scusatemi ma ho veramente bisogno di un consiglio ):
1) terminando cosi' il thread ( con la TerminateThread ), premetto che in
quel thread non vado a scrivere sull'heap e quindi, come dice il Ritcher, mi
scongiuro parecchi problemi, IN CHE PERICOLI POTREI INCORRERE???
avrei voluto usare come sostituzione la SuspendThread - ResumeThread pero'
ho letto che piu' di 127 volte non posso farlo e quindi mi e', inutile...
2) come posso utilizzare la WaitForSingleObject e, piu' importante, fa al
caso mio??? Premetto che con questa tecnica del TerminateThread il programma
funziona, ho alcuni problemi 1 volta su 30, cioe' la radio mi vede che
secondo lei il pacchetto in tx e' sporco e non mi esegue il comando, es.
cambio frequenza...
3) Immediatamente dopo la TerminateThread e prima della CloseHandle dovrei
pulire il buffer con la PurgeComm???  (l' ho provato ma mi sembra che non
funzioni bene )
4) La TerminateThread e' bene che la metta prima o dopo la
EnterCriticalSection???
P.S. uso come piattaforma Windows CE, ma non ho problemi di consulo
batteria, perche' il sistema e' instalato su una scheda PC104 che e' sempre
alimentata dal cavo...
Ciao, scusate la lungezza del testo, e comunque grazie in anticipo!!!

 scritti sul buffer di tx dalla MakePolling
E` quasi sempre sbagliato fare I/O sulla seriale da piu` thread. Sarebbe
meglio che tu scrivessi uno e un solo thread che si occupi soltanto
dell'I/O, e altri thread che lo "pilotano". In questo modo avresti piu`
controllo su cio` che trasmetti.
--
Lorenzo

 controllo su cio` che trasmetti.
quindi tu dici che dovrei utilizzare lo stesso thread per fare polling e per
mandare i messaggi???
e' un'idea buona, quindi io parto, all'avvio del programma, con il polling,
poi, quando l'utente preme un pulsante, entro nel blocco dell'else che sta
dentro il thread e quindi mando il messaggio...
qualcosa del genere:
for (;;)
{
    entercriticalsection // per schedulare i messaggi in coda
    // la variabile semaforo e' spenta ( o gestisco la WaitForSingleObject )
e faccio polling
    if (!bSemaphore)
    {
        // polling
    }
    else
    {
        // gestisco il messaggio
    }
    leavecriticalsection //
}
tu dici qualcosa di simile???
un'ultima cosa, per segnalare che e' partito un messaggio, mi conviene usare
la varibile bSemaphore o la CreateEvent???
se si, mi consigli come usare la createevent???
ciao e grazie!!!

 la varibile bSemaphore o la CreateEvent???
Sicuramente ti consiglio di usare gli eventi, cosi` il thread non
consumera` tempo di CPU non necessario. Gli eventi sono semplici da
usare; all'inizio dell'esecuzione del tuo programma ne crei uno:
CreateEvent( NULL, FALSE, FALSE, "EventoPippo");
Non importa memorizzare l'handle, lo puoi ritrovare in ogni thread con
LoadEvent() come ti ho mostrato sopra.
Infine nel codice che fa partire la trasmissione basta che usi
SetEvent():
SetEvent( hIlTuoEvento);
Questo fara` passare l'evento nello stato segnalato e "svegliera`" il
thread di gestione.
--
Lorenzo

 WaitForSingleObject().
meglio, molto meglio la sezione critica. In molti casi riesce ad 
evitare la costosa chiamata (interna) a WaitForSingleObject con una 
semplice operazione di test&set atomico
-- 
 < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
     Don't stand, REACT!      version 0.0.20. C, C++ and ASM developers
                              and beta testers are welcome!