Riprendo la risposta di Serati al mio sfizio di spostare avanti e indietro un Button (o altro oggetto) su una Grid, con un uso accorto di Thread, e delegati: invocati tramite Dispatcher.Invoke Dim task As New Task(Sub() System.Threading.Thread.Sleep(2000) 'sleep 2 secondi Dispatcher.Invoke(Sub() Button1.SetValue(Grid.RowProperty, 1) Button1.SetValue(Grid.ColumnProperty, 1) End Sub) System.Threading.Thread.Sleep(2000) 'sleep 2 secondi Dispatcher.Invoke(Sub() Button1.SetValue(Grid.RowProperty, 0) Button1.SetValue(Grid.ColumnProperty, 0) End Sub) MessageBox.Show("Fine del Va e vieni...") End Sub) task.Start() “Così facendo - aggiungeva l’amico - lo sleep si applica al thread che crei tu, non a quello di UI. E l'operazione funziona.” Successivamente ho ampliato il discorso a una girandola sulle 4 celle di una Grid 2 x 2, con una oluzione più completa e compatta possibile: Imports System.Threading.Tasks Imports System.Threading Class MainWindow Sub SpostaSuGrid(ByVal R As Integer, ByVal C As Integer) Button1.SetValue(Grid.RowProperty, R) Button1.SetValue(Grid.ColumnProperty, C) End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click ' For i = 1 To 5 Dim GeneRCasuali As New Random Dim NCas = GeneRCasuali.Next(250, 1000) Dim task As New Task(Sub() Thread.Sleep(NCas) 'sleep casuale da 0,25 a 1 sec. Dispatcher.Invoke(Sub() SpostaSuGrid(0, 1)) Thread.Sleep(NCas) 'sleep casuale da 0,25 a 1 sec. Dispatcher.Invoke(Sub() SpostaSuGrid(1, 1)) Thread.Sleep(NCas) 'sleep casuale da 0,25 a 1 sec. Dispatcher.Invoke(Sub() SpostaSuGrid(1, 0)) Thread.Sleep(NCas) 'sleep casuale da 0,25 a 1 sec. Dispatcher.Invoke(Sub() SpostaSuGrid(0, 0)) 'MessageBox.Show("Fine del Va e vieni...") ' Dispatcher.InvokeShutdown() 'TROPPO DRASTICO: cessa il PROGRAMMA! End Sub) task.Start() ' Next ' MessageBox.Show(balla.IsCompleted) ' Viene comunque eseguita... End Sub End Class Ciò grazie alle 2 direttive Imports e soprattutto col metodo SpostaSuGrid di argomenti R (riga) e C (colonna). Tuttavia la cosa non mi soddisfa, per due motivi: 1) Incapsulando il tutto in un ciclo For i = 1 To 5. . . Next nascono pasticci imprevisti (per cui ne ho “ucciso” le istruzioni ==> commenti; 2) non trovo bello ripetere le 4 invocazioni, senza riuscire a inquadrarle in due cicli For/Next nidificati. Il fatto è che ciò è invece del tutto agevole con i Form, tramiti la coppia di istruzioni del tipo seguente: Application.DoEvents() System.Threading.Thread.Sleep(500) Che purtroppo NON lavora in WPF – è comunque un FATTO – che RIFIUTA Application.DoEvents. Insomma chiedo lumi...
|