View Full Version : [.NET] Windows forms e modal dialogs...
^TiGeRShArK^
07-02-2008, 16:03
Come si fanno a visualizzare 'sti benedetti dialoghi modali con i windows forms?
ho provato a fare così:
private void copyAllWorker_DoWork(object sender, DoWorkEventArgs e)
{
waitDialog = new WaitDialog();
Application.Run(waitDialog);
waitDialog.ShowDialog(this);
foreach (string watchedDir in watchedDirsListbox.Items)
{
waitDialog.currentDirectory.Text = "Copia di " + watchedDir;
.......
}
}
private void copyAllWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
waitDialog.Dispose();
}
Però praticamente non funziona una mazza.
Accade questo:
1) Il dialogo non è modale.
2) Mi impalla tutto.
Prima non mi veniva nemmeno visualizzato perchè non utilizzavo Application.run(), mentre ora viene visualizzato ma haquesto comportamento non desiderato.
Tenendo conto che lo sto lanciando da un thread diverso da quello dell'Event Listener grafico di windows, c'è qualche altra operazione particolare da fare oltre ad Application.run?
In pratica mi servirebbe qualcosa come lo SkingUtilities.invokeLater() di java credo...
Qualcuno ha idea di cosa sto sbagliando? :fagiano:
Einstein
07-02-2008, 20:17
Non conosco il contesto dell'applicazione, ma ci sono diverse cose che non quadrano:
1. Non puoi dichiarare una variabile "waitDialog" locale ad un metodo, e poi farne la dispose in un altro.
2. Da quanto vedo stai usando il BackgroundWorker, quindi innanzitutto il tuo dialog modale WaitDialog va istanziato dall'applicazione principale con un waitDialog.ShowDialog() e non nel worker, e deve girare nel thread della form proncipale.
3. Il tuo WaitDialog sarà quello che eseguirà il "lavoro sporco", quindi sarà lui il detentore del BackgroundWorker (a meno che non ti serva anche da altre parti).
4. Il BackgroundWorker del tuo WaitDialog dovrà sottoscriversi agli eventi DoWork, RunWorkerCompleted e, se vuoi riportare un progresso, ProgressChanged, dove, nel primo fai i tuoi lavori.
5. Il processo inizia invocando il metodo RunWorkerAsync() del BackgroundWorker.
Spero di aver centrato la cosa...
^TiGeRShArK^
07-02-2008, 22:12
Non conosco il contesto dell'applicazione, ma ci sono diverse cose che non quadrano:
1. Non puoi dichiarare una variabile "waitDialog" locale ad un metodo, e poi farne la dispose in un altro.
Ovviamente è un field dato che non è dichiarato in nessuno dei due metodi :D
2. Da quanto vedo stai usando il BackgroundWorker, quindi innanzitutto il tuo dialog modale WaitDialog va istanziato dall'applicazione principale con un waitDialog.ShowDialog() e non nel worker, e deve girare nel thread della form proncipale.
...alla fine ho adottayo questa soluzione...
..ma quindi con le window forms non è possibile lanciare componenti grafici dal thread diverso da quello del gestore degli eventi? :mbe:
In java si fa tranquillamente :fagiano:
3. Il tuo WaitDialog sarà quello che eseguirà il "lavoro sporco", quindi sarà lui il detentore del BackgroundWorker (a meno che non ti serva anche da altre parti).
In effetti avrei anche potuto farlo così che mi pare + pulito..
Per ora ho reso "master" il background worker che mi uccideva con un dispose il dialogo modale quando finiva il suo compito...
4. Il BackgroundWorker del tuo WaitDialog dovrà sottoscriversi agli eventi DoWork, RunWorkerCompleted e, se vuoi riportare un progresso, ProgressChanged, dove, nel primo fai i tuoi lavori.
5. Il processo inizia invocando il metodo RunWorkerAsync() del BackgroundWorker.
Spero di aver centrato la cosa...
gli ultimi due punti già funzionavano :D
grazie per l'aiuto :p
e ora di nuovo al lavoro.. :sob: (con java però :p)
Einstein
08-02-2008, 11:03
Ovviamente è un field dato che non è dichiarato in nessuno dei due metodi :D
Hai ragione, scusa... :D
..ma quindi con le window forms non è possibile lanciare componenti grafici dal thread diverso da quello del gestore degli eventi? :mbe:
In java si fa tranquillamente :fagiano:
Non puoi accedere agli oggetti grafici da un thread diverso da quello in cui gira l'interfaccia utente. Devi usare il metodo Invoke() pssando un delegate come parametro.
^TiGeRShArK^
08-02-2008, 19:49
Hai ragione, scusa... :D
Non puoi accedere agli oggetti grafici da un thread diverso da quello in cui gira l'interfaccia utente. Devi usare il metodo Invoke() pssando un delegate come parametro.
No, si può fare ma *potrebbe creare casini*..
Infatti per questo chiedevo dell'equivalente per c# di SkingUtilities.invokeLater() che si occupa proprio di effettuare cambiamenti a componenti grafici da un thread diverso in maniera corretta... e mi sa che il tuo ultimo post ha risposto alla mia domanda :D
Come funziona quindi questo metodo Invoke() .. o meglio.. dove lo trovo? :D
Einstein
09-02-2008, 13:35
No, si può fare ma *potrebbe creare casini*..
Il runtime .NET solleva un eccezione sicuramente, quindi non ti permette di farlo.
Come funziona quindi questo metodo Invoke() .. o meglio.. dove lo trovo? :D
Puoi trovare maggiori info qui: http://msdn2.microsoft.com/en-us/library/zyzhdc6b.aspx
Il BackgroundWorker, internamente, utilizza questo metodo per gestire l'evento ProgressChanged, dove, nel gestore associato all'evento, puoi accedere ai controlli in modo thread safe. Ad esempio:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// progressBar1 è un controllo ProgressBar all'interno della form
this.progressBar1.Value = e.ProgressPercentage;
}
^TiGeRShArK^
09-02-2008, 13:42
Il runtime .NET solleva un eccezione sicuramente, quindi non ti permette di farlo.
Puoi trovare maggiori info qui: http://msdn2.microsoft.com/en-us/library/zyzhdc6b.aspx
Il BackgroundWorker, internamente, utilizza questo metodo per gestire l'evento ProgressChanged, dove, nel gestore associato all'evento, puoi accedere ai controlli in modo thread safe. Ad esempio:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// progressBar1 è un controllo ProgressBar all'interno della form
this.progressBar1.Value = e.ProgressPercentage;
}
ehmm..
finora non me l'ha mai sollevata l'eccezione :D
in pratica cambiavo il testo di una label direttamente dal doWork del backgroundworker.... cosa che sapevo essere sbagliatissima, però a quanto pare funzionava :p
Ora che so dell'esistenza di invoke lo cambierò in quel modo oppure implementerò il metodo ProgressChanged (che non avevo ancora fatto perchè è in una storia successiva :D)
Einstein
09-02-2008, 14:44
Se lo fai dal BackgroundWorker, ok, ma perché è lui che ti pone in un contesto thread safe... Se lo fai fuori dal BackgroundWorker, hai un'eccezione (a meno di non usare Invoke()).
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.