Login Register
domenica 20 maggio 2012
 
Forums

I Forum di WPF Tips & Tricks
Girandola di oggetti movimentati in una Grid, con Thread, Dispatcher e delegati
Last Post 25 giu 2011 01:52 by Gianni Giaccaglini. 2 Replies.
Printer Friendly
Sort:
PrevPrev NextNext
You are not authorized to post a reply.
Author Messages
Gianni Giaccaglini
Advanced Member
Advanced Member
Posts:124
Avatar

--
21 giu 2011 02:29  
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...
Alessandro Del Sole [MVP]
Team
Team
Posts:121
Avatar

--
24 giu 2011 05:27  
Prova a vedere questo link: http://dedjo.blogspot.com/2007/08/h...n-wpf.html
Ci sono molti blog post similari su Internet, sicuramente qualcuno ti è utile.
Gianni Giaccaglini
Advanced Member
Advanced Member
Posts:124
Avatar

--
25 giu 2011 01:52  
Grazie Alessandro! Il link indicato mi è stato utile perché affronta il tema in modo organico. In realta - giuro! - avevo già fatto una ricerca su "DoEvents in WPF" in particolare scoprendo un trucco che, per così dire, "resuscita" DoEvents semplicemente con l'istruzione:
System.Windows.Forms.Application.DoEvents()

che ahimè mi veniva regolarmente rigettata, per cui ero passato al più organico ma ben più complesso e impegnativo Dispatcher & via di seguito. L'ottimo sito però mette in chiara evidenza che SI DEBBONO FISSARE I RIFERIMENTI ALLA DLL System.Windows.Forms, operazione da non confondere con una direttiva Imports! va fatta dal menu Progetto > Aggiungi riferimento... con quel che segue.

A questo punto propongo al volo questa routine:
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button3.Click
For riga = 2 To 0 Step -1
For colonna = 2 To 0 Step -1
Button1.SetValue(Grid.RowProperty, riga)
Button1.SetValue(Grid.ColumnProperty, colonna)
Thread.Sleep(2000)
System.Windows.Forms.Application.DoEvents()
Next
Next
End Sub

Elementare? Sì ma funzionante senza intoppi e soprattutto caratterizzata da due vantaggi:
a) permette l'utilizzo tranquillo di loop di ogni tipo (mentre Dispatcher fa ammattire con i For/Next: la stessa Guida mette in guardia, al riguardo, dichiarando possibilità di imprevisti, che anch'io ho potuto provare);
b) rende più semplice e indolore il passaggio da soluzioni Forms - ove Application.DoEvents è "di casa" - a soluzioni WPF che lo rifiuta (perché qui Application è un'altra cosa, basata sul tandem Application.xame e Application.vb).

Molto istruttivo davvero!
You are not authorized to post a reply.

Active Forums 4.2
  
hd porn
 
© 2009-2011 WPF Tips&Tricks Team - Visual Basic Tips&Tricks Network
 
porno izleporno izle