Waitdialog and thread

venerdì 05 settembre 2008 - 15.44

slackewix Profilo | Newbie

ciao a tutti, ho una cosetta che non riesco a risolvere: ho creato un classico, semplicissimo waitdialog da mostrare all'utente mentre attende (caricamento, ricerca ecc). Dal momento che vorrei farlo animato però (ho messo una progressbar con maruqee style e un counter di millisecondi), sto provando a chiamarlo in un thread separato. Il dialog però appare sempre solo alla fine delle operazioni e non all'inizio, e per giunta è fermo. Posto di seguito un po' di codice:


PleaseWait workerObject = new PleaseWait(); Thread workerThread = new Thread(workerObject.DoWork); workerThread.Start(); while (!workerThread.IsAlive); Thread.Sleep(1); sMDIChild.MdiParent = sMDIParent; sMDIChild.Show(); sMDIChild.Activate(); sMDIChild.BringToFront(); workerObject.RequestStop(); workerThread.Join(); public class PleaseWait { public void DoWork() { WaitDialog.WaitForm oWait = null; while (!_shouldStop) { oWait = new WaitDialog.WaitForm(); oWait.Show(); } if (oWait != null) oWait.KillMe(); } public void RequestStop() { _shouldStop = true; } private volatile bool _shouldStop; }



grazie dell'aiuto, come sempre
p.s.: non credo c'entri nulla, ma il waitdialog è compilato in una dll a parte

[EDIT]
ho fatto qualche prova anche con il backgroundworker, ma il risultato non cambia

Faelar Profilo | Junior Member

Prova così:

dopo la show chiama inserisci: Application.DoEvents(); Questa chiamata passa il controllo al sistema, che si occuperà di visualizzare la tua dialog.

Poi lungo il resto del codice inserisci ogni tanto la stessa chiamata, così il sistema si occuperà di rinfrescare la dialog.



Se non è chiaro, chiedi pure.

slackewix Profilo | Newbie

si, ho fatto la prova, ma l'esito è sempre lo stesso. Seguendo il debug però ho notato che la chiamata al Show() del secondo form viene effettuata prima della chiamata al form di attesa, nonostante da codice sia l'inverso. Il che mi fa pensare che venga eseguita prima la chiamata sul thread principale e poi sull'altro. Cambiando la priorità del thread non succede nulla. Ossia, parte il thread secondario, ma prima di arrivare alla chimata Show() del form di attesa ripassa al thread principale e apre il secondo form. Dopodichè torna al thread secondario e apre il form di attesa. boh?!?

Faelar Profilo | Junior Member

quindi, per capirci, arriva prima la sMDIChild.Show() della PleaseWait.Show()?

Non è che la continua creazione del form di wait gli rompe un po' le scatole?


Cmq adesso provo a ricreare il tuo esempio e faccio due prove...




Luca.

slackewix Profilo | Newbie

>quindi, per capirci, arriva prima la sMDIChild.Show() della PleaseWait.Show()?


esattamente!
Il pleasewait non è nient'altro che un form con una progressbar sopra (con style marquee) e un'immagine (statica), compilato in una dll a parte.
grazie

Faelar Profilo | Junior Member

Ok, cambiando il ciclo while così a me funziona

while (!_shouldStop)
{
if (oWait == null)
{
oWait = new WaitDialog.WaitForm();
oWait.Show();
}

Application.DoEvents();
}

slackewix Profilo | Newbie

si in effetti così non si blocca + il pleasewait sulla progress. Però viene ancora visualizzato dopo il l'altro form. Nel senso che cliccando sulla voce di menu che mi apre il form, si visualizza il secondo form e alla fine per qualche attimo vedo il pleasewait apparire e la progressbar che parte. e poi naturalmente sparisce perchè la routine è al termine.

Faelar Profilo | Junior Member

Ok, caricavo in un modo diverso il form...

Sono riuscito a replicare il tuo problema, e per risolverlo ho dovuto inserire una funzione nella classe "PleaseWait" che mi restituisse true solo una volta che la dialog con la scrollbar è visibile.

Così a me funziona, sempre se ho capito come carichi tu il nuovo form.


Ecco il codice della classe PleaseWait:

public class PleaseWait
{
dlgWaitDialog oWait = null;

public void DoWork()
{
while (!_shouldStop)
{
if (oWait == null)
{
oWait = new dlgWaitDialog();
oWait.Show();
}

Application.DoEvents();
}

if (oWait != null)
oWait.Dispose();
}

public void RequestStop()
{
_shouldStop = true;
}

public bool IsShowed()
{
if (oWait == null)
return false;
else
return oWait._IsShow;
}

private volatile bool _shouldStop;
}


Questa è la modifica nella dialog:
public bool _IsShow = false;

private void dlgWaitDialog_Activated(object sender, EventArgs e)
{
_IsShow = true;
}


E questa è la parte che inizializza la dialog:
Thread workerThread = new Thread(workerObject.DoWork);
workerThread.Start();
while (!workerObject.IsShowed()) ;



Se c'è qualcosa di poco chiaro dimmi pure.

slackewix Profilo | Newbie

tutto chiarissimo e perfetto, funziona a meraviglia! grazie

slackewix Profilo | Newbie

ciao luca, sai che mi sta succedendo una cosa veramente strana? caricando un form con il pleasewait le maskedtextbox del form non sono + cliccabili: nel senso che se ci arrivo sopra con i tab non ho problemi, ma se ci clicco sopra con il mouse il cursore non appare, non mi seleziona il testo e così via, come se proprio non ricevesse l'input dal mouse. Se tolgo il caricamento del pleasewait invece non succede nulla.
Ancora + strano è che succede solo esclusivamente con le maskedtextbox, tutti gli altri controlli rispondono come al solito. Preciso che al pleasewait non ho aggiunto nulla (tipo disabilitazione dei controlli in fase di caricamento e simili). Puoi vedere se riesci a riprodurre l'errore? grazie
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-2023
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5