[VB.NET 2005] - Gestire Thread

martedì 30 giugno 2009 - 17.13

petitmax Profilo | Newbie

Salve a tutti,
spero di aver indovinato la sezione dove postare il problema e soprattutto che non sia stato gia affrontato l'argomento (ma da una ricerca fatta non mi sembra sia stato gia trattato).

Vengo al dunque:
-----------------
sto creando un'applicazione (VB.NET 2005) che ha un bel pò di inizializzazioni da compiere prima che questa si renda disponibile.
Per "distrarre" l'utente avevo pensato a uno splash screen (che chiamerò frmSplash) da visualizzare con una progress bar di tipo marquee nel frattempo che le inizializzazioni del form principale (frmMain) vengano completate. ...NON L'AVESSI MAI FATTO !!!

Nei vari tentativi che ho fatto mi appare un solo frmSplash e non l'altro...oppure direttamente frmMain senza passare da frmSplash...insomma tentativi falliti miseramente.

La mia intenzione è:
- all'avvio far vedere frmSplash con questa ProgressBar che scorre bella fluida e non a scatti;
- subito dopo partono in backgroud (quindi nascoste all'utente) tutte le inzializzazioni del caso (query, popolamento combo, etc.);
- terminate la inizializzazioni vorrei che frmSpalsh si chiudesse in quanto non voglio che se la frmMain viene ridotta a icona si veda frmSplash;
- una volta terminato di utilizzare il programma (cioè quando la frmMain viene chiusa) vorrei che si chiudesse tutto il programma (E NON CHE TORNI IN PRIMO PIANO LA frmSplash come è successo a me).

Jeremy Profilo | Guru

Ciao
per fare in modo che, al termine delle operazioni eseguite nella frmSplash .. si apra il frmMain, ...nelle proprietà di progetto, devi impostare il frmMain come oggetto di avvio ed il frmSlplah come Schermata iniziale.

Spero sia quello di cui avevi bisogno .... eventualmente ... facci sapere...
Ciao

petitmax Profilo | Newbie

Innanzitutto grazie Jeremy per avermi risposto.
Purtroppo il metodo suggerito da te non dà i risultati sperati.

Mi spiego: come da te indicato ho specificato i due form (frmSplash e frmMain) nelle proprietà del progetto rispettivamente come "schermata iniziale" e "form di avvio".

Nel codice di frmSplash creo un'istanza di frmMain e su questa vado a "lavorare", impostando tutte le proprietà di cui ho bisogno.

Quando queste inizializzazioni sono terminate frmSplash viene sì chiuso...ma perdo anche il riferimento a frmMain che avevo creato e di conseguenza tutte le sue inizializzazioni. A questo punto la FormMain che appare sembra essere chiamata da un'altra istanza di frmMain in quanto non ha i settaggi fatti da me nell'istanza creata in frmSplash (persi probabilmente quando si è chiuso frmSplash).

Non solo...

nella frmSplash ho messo una ProgressBar con lo stile impostato sul sipo Marquee...ma questa rimane ferma come se fosse bloccata e non è questo quello che volevo.
Quella progress bar dovrebbe essere visibile, insieme a tutta la frmSplash, compresa l'animazione e dovrebbe "distrarre" l'utente durante le non brevissime inizializzazioni di FormMain.

Spero di non essere stato troppo contorto, in tal caso posso postare del codice.

Max

Jeremy Profilo | Guru

Ciao Massimiliano.
Ci credo che non succede quello che ti aspetti .

Ci sono, a parer mio, alcune cosine da sistemare ....
Innanzitutto, l'istanza al quale fai riferimento dallo splash screen, non è la stessa che si apre al termine dello splashscreen, pertanto è normale ciò che ti succede ... potresti provare a far riferimento all'istanza predefinita .... dico "potresti provare" perchè non ho la certezza che sia già stata creata alla partenza dello splash screen, dovrei fare una prova ... ma forse è meglio che la fai tu.

Per quanto riguarda la barra, dipende da come gestisci la progressione ed il refesh del suo contenitore(Form).

Se mostri un pò di codice .... ci ragioniamo insieme.

Facci sapere...
Ciao

petitmax Profilo | Newbie

Ciao...
ancora grazie per la disponibiltà e scuse per non essermi collegato prima ma prima eimpegni di lavoro e poi finalmente ( e sottolineo finalmente) un pò di sole mi hanno tenuto lontano dal progetto.

Mi chiedevi un po di codice ? eccolo.

Questo è il codice di FormSplash:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Questo invece è il codice di FormMain (di cui riporto però, per motivi di spazio, solo i metodi pubblici):

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Mi spiace essermi dilungato tanto...

Ovviamente sono ben accette critiche/suggerimenti e correzioni (oltre a quelle richieste).
Saluti
Max

Jeremy Profilo | Guru

Ciao Massimiliano.
Purtroppo, se vuoi gestire gli oggetti del MainForm dallo splashscreen, devi impostare l'avvio della tua applicazione in un modo diverso, in quanto, con le attuali impostazioni di avvio applicazione, al termine dell'esecuzione dello splashscreen, viene creata una nuova istanza del Form di avvio, che non è la stessa al quale fai riferimento dallo splashscreen.
Quindi, anche eliminando questa riga di codice:
>frmMain = New FormMain
il discorso non cambia.
Per ottenere il risultato che ti aspetti, devi, a questo punto, impostare lo splashscreen come form di avvio, e gestire tutto da codice (come in parte hai già fatto).
Il problema che si potrebbe presentare in questo caso, è che chiudendo lo splashscreen, (me.close) l'applicazione verrebbe terminata (in quanto form di avvio).
Se non sbaglio, ci dovrebbe essere un'impostazione che permette di scegliere se terminare l'applicazione alla chiusura dell'ultimo form od alla chiusura del form di avvio.
Dovresti cercarla ed impostarla al caso tuo.
Altrimenti, ci potrebbero tante altre strade da seguire ma, fossi in te, comincerei con questa

Facci sapere....
Ciao

petitmax Profilo | Newbie

Ok...
Grazie del suggerimento.
Cambierò la logica di avvio del progetto e ti faccio sapere.

A presto
Max

petitmax Profilo | Newbie

>Il problema che si potrebbe presentare in questo caso, è che
>chiudendo lo splashscreen, (me.close) l'applicazione verrebbe
>terminata (in quanto form di avvio).
>Se non sbaglio, ci dovrebbe essere un'impostazione che permette
>di scegliere se terminare l'applicazione alla chiusura dell'ultimo
>form od alla chiusura del form di avvio.
>Dovresti cercarla ed impostarla al caso tuo.
>Altrimenti, ci potrebbero tante altre strade da seguire ma, fossi
>in te, comincerei con questa
>
>Facci sapere....
>Ciao
>

Eccomi quà...
ho ottimizzato il codice in seguito ai tuoi suggerimenti (SpalshScreen parte come form di avvio, l'istanza di FormAvvio la creo nello splashScreen e visualizzo correttamente, etc.etc.).

Ho però ancora il problema della fluidità dello SplahScreen stesso (che poi è il problema che mi ha spinto a scrivere quì).
Mi spiego meglio: mentre il FormMain viene inizializzato da SplaShScreen quello che dovrei vedere è


573x271 17Kb

(con la progress bar animata ovviamente)

invece vedo questo:

570x265 8Kb



Aspetto buone nuove
Max

Jeremy Profilo | Guru

Ciao Massimiliano.
Si .... quello è un'altro problema....non centra con il fatto che sia uno splashscreen o meno.
Per risolvere, ci sono diverse strade, più o meno complicate a seconda del risultato che vuoi ottenere.

Cominciamo con la più semplice, poi eventualmente .........

Nel ciclo di incremento della progressbar, inserisci un
Me.refresh Application.DoEvents
ad ogni step del ciclo.....questo permette al processore di gestire anche la parte grafica del form.

Facci sapere...
Ciao.

petitmax Profilo | Newbie

>Nel ciclo di incremento della progressbar, inserisci un
>
>Me.refresh
>Application.DoEvents
>
>ad ogni step del ciclo.....questo permette al processore di gestire
>anche la parte grafica del form.
>

Mi sa che mi sono spiegato male: la progress bar che ho inserito è di tipo Marquee (tipo quella che viene visualizzata all'avvio di Windows).
Ho scelto questa perché all'avvio dell'applicazione non c'è solo una query ma vengono effettuate ma anche altre inizializzazioni delle quali non posso prevederne la durata.

L'idea quindi era questa:
- carico lo splash con la progress bar che va....va sempre.....all'infinito...(così da tenere "distratto" l'utente)
- nel frattempo, in background, mi inizializzo la FormMain
- quando FormMain è pronta chiudo lo splashScreen e mostro la FormMain.

Scusa se mi sono spiegato male.
Max

Jeremy Profilo | Guru

Ciao.
Questo, ti succede, perchè esegui le operazioni di inizializzazione del form main, nell'evento shown dello splashscreen.
Dici di eseguire le operazioni in background ma, evidentemente, non è così.
Per background, intendo l'esecuzione delle operazioni in un thread separato da quello principale, il che, ti porterebbe anche a dover gestire operazioni cross thread.
Prova a spostare il codice che utilizzi, per inizializzare il form, nell'evento Tick di un timer in modo da poterlo eseguire con un ritardo di 1 secondo o due rispetto alla visualizzazione del form e vedi che risultato ottieni ..... se non soddisfacente, rimangono due soluzioni:
- O inizializzi e visualizzi la progressbar da un thread separato
- O esegui le operazioni di inizializzazione del Form in un thread separato.

Facci sapere....
Ciao

petitmax Profilo | Newbie

>Per background, intendo l'esecuzione delle operazioni in un thread
>separato da quello principale [...]
Ok, scusami...ho usato un termine in maniera impropria.
Background lo intendevo come l'esecuzione di codice nascosto alla vista dell'utente.

>Prova a spostare il codice che utilizzi, per inizializzare il
>form, nell'evento Tick di un timer in modo da poterlo eseguire
>con un ritardo di 1 secondo o due rispetto alla visualizzazione
>del form e vedi che risultato ottieni ..... se non soddisfacente,
>rimangono due soluzioni:
>- O inizializzi e visualizzi la progressbar da un thread separato
>- O esegui le operazioni di inizializzazione del Form in un thread
>separato.
Preferirei passare direttamente all'opzione thread...oggi o domani che il db si riempie (e quindi i tempi di risposta della query si allungano) uno o due secondi potrebbero non bastare più e quindi mi vedrei costretto a ricompilare tutto solo per aumentare il tick.

Per la gestione dei thread avrei bisogno di qualche dritta...ne ho solo sentito parlare e li conosco solo in modo concettuale.
Se mi aiutassi a utilizzarli mi faresti un grosso favore.

Grazie ancora per la disponibilità e per il tempo che mi stai concedendo.
Max

Jeremy Profilo | Guru

Ciao Massimiliano.
Non complichiamoci la vita più di quanto è già complicata.
Hai frainteso il mio primo suggerimento ..... il tempo dopo cui viene scatenato l'evento Tick del Timer, non centra nulla con il tempo di esecuzione del cosice per inizializzare il form main ma, serve solo per dare il tempo allo splashscreen di aggiornare la parte grafica prima di cominciare ad eseguire il codice.
Se il risultato che ottieni non è soddisfacente, stai tranquillo che non mi tiro indietro ...... ti aiuterò nella seconda soluzione.
Ma se riesci ad ottenere un buon risultato con il timer ..... evitiamo un mucchio di problemi e, concettualmente, potrei comunque spiegarti come funziona il multithreading (nel limite delle mie conoscenze .... ovviamente), magari passandoti anche un progettino di esempio.

Facci sapere....
Ciao

petitmax Profilo | Newbie

Sorry...
mi metto all'opera con il timer e ti faccio sapere.

Max

P.S.: grazie ancora per la disponibilità.

petitmax Profilo | Newbie

Dunque:

dopo diversi "aggiusti" quello che segue è il miglior risultato ottuenuto finora.

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra


Di sicuro un grosso passo avanti lo abbiamo fatto anche non va ancora benissimo.
Mi spiego: lo SplashScreen parte, si vede bene e la ProgressBar si avvia e scorre fluida ma solo fino a un certo punto. Si blocca quando inizia l'esecuzione della parte di codice riguardante l'inzializzazione del FormMain e resta bloccata fin quando questa inizializzazione non termina.
Da quel momento in poi il programma procede correttamente (lo SplashScreen si chiude, FormMain viene mostrato e prende il controllo dell'applicazione).

Spero sia chiaro.
Max

Jeremy Profilo | Guru

Ciao Massimiliano.
Lo temevo .... passiamo alla seconda soluzione.
Oggi non posso darti troppa retta, ad ogni modo, se non hai fretta, domani vedo di allegarti un progettino di esempio, commentato.

Ciao

petitmax Profilo | Newbie

ok, grazie lo aspetto.

Jeremy Profilo | Guru

Ciao Massimiliano.
Come d'accordo, ti allego un piccolo progettino di esempio con qualche commento.
Spero che sia quello che ti serviva.
Facci sapere...
Ciao

petitmax Profilo | Newbie

Grazie Jeremy,

per il momento ti scrivo solo per ringraziarti...

La soluzione che mi hai inviato è stata creata con una versione successiva di Visual Studio 2005 ?
Te lo chiedo perché non riesco ad aprirla ma non rappresenta un problema visto che riesco ad aprire i file VB con un normale editor di testo.

Ciao
Max

Jeremy Profilo | Guru

Ciao Massimiliano.
>La soluzione che mi hai inviato è stata creata con una versione successiva di Visual Studio 2005 ?
Si .... uso Vb 2008, ad ogni modo, come hai già detto tu, è sufficiente che copi incolli il codice che trovi nei file .vb.
Nelle proprietà di progetto, ricordati di impostare il Form1 come Oggetto di avvio e nulla come shermata iniziale.

Facci sapere....
Ciao

petitmax Profilo | Newbie

Funziona !!!

perdona l'estrema sintesi...ma è la realtà dei fatti.

Quell'esempio mi è stato di grosso aiuto.

Non mi rimane che ringraziarti per il tempo che mi hai dedicato.

Max
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5