Guida al Visual Basic .NET
Capitolo 89° - BackgroundWorker e FileSystemWatcher
BackgroundWorker
Dopo aver analizzato nel dettaglio la struttura e il funzionamento del sistema di threading, veniamo ora a vedere alcuni controlli che implementano questo meccanismo "dietro le quinte". Il primo di questi è BackgroundWorker, un controllo senza interfaccia grafica, che nelle Windows Application rende molto più facile l'utilizzo di thread separati per compiti diversi: infatti fornisce metodi e proprietà che fanno da wrapper a un thread separato. Ecco una lista dei membri più usati:
Ora, il BackgroundWorker lavora come descritto di seguito. La procedura principale che deve essere eseguita nel thread separato va posta
in un evento speciale del controllo, chiamato DoWork: attraverso il parametro "e" è possibile anche ottenere altri dati necessari
alle operazioni da svolgere. Una volta che tutto il codice in DoWork è stato completato, viene lanciato l'evento RunWorkerCompleted.
Tale evento viene comunque generato anche nel caso in cui il sorgente abbia dato esito negativo (ad esempio a causa del verificarsi di
eccezioni gestite e non), oppure si sia richiamata la procedura CancelAsync. Sempre all'interno di DoWork si può usare il metodo ReportProgress
per comunicare all'applicazione principale un avanzamento del livello di completamento del lavoro. Imports System.ComponentModel 'In System.ComponentModel Class Form1 Private Sub txtDir_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles txtDir.Click Dim Open As New FolderBrowserDialog Open.Description = "Scegliere la cartella da analizzare:" If Open.ShowDialog = Windows.Forms.DialogResult.OK Then txtDir.Text = Open.SelectedPath End If End Sub Private Sub cmdAnalyze_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles cmdAnalyze.Click If cmdAnalyze.Text = "Analizza" Then 'Controlla che la cartella esista If Not IO.Directory.Exists(txtDir.Text) Then MessageBox.Show("Cartella inesistente!", "Sizing", _ MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End If 'Fa partire il BackgroundWorker, passandogli come unico 'argomento il percorso della cartella da analizzare bgwScan.RunWorkerAsync(txtDir.Text) 'Modifica il testo del pulsante, così da potergli 'assegnare anche un altro compito cmdAnalyze.Text = "Ferma" Else 'Il testo non è "Analizza". Deve per forza essere '"Ferma", quindi termina l'operazione forzatamente bgwScan.CancelAsync() cmdAnalyze.Text = "Analizza" End If End Sub Private Sub bgwScan_DoWork(ByVal sender As Object, _ ByVal e As DoWorkEventArgs) Handles bgwScan.DoWork 'Ottiene tutti i files presenti nella cartella: '- e.Argument ottiene lo stesso valore passato a ' RunWorkerAsync: in questo caso contiene una stringa '- il pattern *.* specifica di cercare files di ogni ' estensione '- l'ultimo argomento comunica di eseguire una ricerca ' ricorsiva analizzando anche tutte le sottocartelle Dim Files() As String = _ IO.Directory.GetFiles(e.Argument, "*.*", _ IO.SearchOption.AllDirectories) 'Dimensione totale Dim Size As Double = 0 'Files analizzati Dim Index As Int32 = 0 'Calcola la dimensiona totale della cartella sommando tutte 'le dimensioni parziali For Each File As String In Files 'FileLen è una funzione di VB6, ma il VB.NET 'implicherebbe di creare un nuovo oggetto FileInfo e 'quindi richiamarne la proprietà Length. In 'questo modo è molto più comodo, anche 'se non proprio conforme alle direttive .NET Size += FileLen(File) Index += 1 'Riporta la percentuale e genera un evento 'ProgressChanged bgwScan.ReportProgress(Index * 100 / Files.Length) 'Controlla se ci sono richieste di cancellazione. 'Se ce ne sono, termina qui la procedura If bgwScan.CancellationPending Then e.Cancel = True Exit Sub End If Next 'Il valore Result di e rappresenta il valore da restituire. 'In questo caso è come se DoWork fosse una funzione. 'Dato che si può passare solo un valore Object, 'mettiamo in quel valore un array di Double contenente 'il numero di files trovati e la loro dimensione complessiva e.Result = New Double() {Files.Length, Size} End Sub Private Sub bgwScan_ProgressChanged(ByVal sender As Object, _ ByVal e As ProgressChangedEventArgs) Handles bgwScan.ProgressChanged 'Visualizza la percentuale sulla barra prgProgress.Value = e.ProgressPercentage End Sub Private Sub bgwScan_RunWorkerCompleted(ByVal sender As Object, _ ByVal e As RunWorkerCompletedEventArgs) Handles bgwScan.RunWorkerCompleted 'Controlla la causa che ha scatenato questo evento If e.Cancelled Then 'Una cancellazione? MessageBox.Show("Operazione annullata!", "Sizing", _ MessageBoxButtons.OK, MessageBoxIcon.Exclamation) ElseIf e.Error IsNot Nothing Then 'Un'eccezione? MessageBox.Show("Si è verificato un errore!", "Sizing", _ MessageBoxButtons.OK, MessageBoxIcon.Error) Else 'O semplicemente la fine delle operazioni 'COnverte il risultato ancora in un array di Double Dim Values() As Double = e.Result lblInfo.Text = String.Format("Sono stati trovati {0} files." & _ "{1}La dimensione totale della cartella è {2:N0} bytes.", _ Values(0), vbCrLf, Values(1)) End If 'Per sicurezza, reimposta il testo del pulsante cmdAnalyze.Text = "Analizza" End Sub End Class
FileSystemWatcher
L'oggetto FileSystemWatcher serve per monitorare files o cartelle in modo da sapere in tempo reale quando vengono modificati, cancellati, aperti o spostati, ed eseguire azioni di conseguenza. Si potrebbe, ad esempio, controllare un file speciale e visualizzare un messaggio di warning se l'utente cerca di aprirlo, o chiedere una password, oppure addirittura spegnere il computer (!!). Questo controllo, come si pu&ograv; intuire, non ha interfaccia grafica. Le sue proprietà interessanti sono:
Bisogna anche dire, però, che nel 99% dei casi questo controllo fa cilecca... infatti non genera nessun evento anche quando dovrebbe. Misteri del .NET Framework!
C#, TypeScript, java, php, EcmaScript (JavaScript), Spring, Hibernate, React, SASS/LESS, jade, python, scikit, node.js, redux, postgres, keras, kubernetes, docker, hexo, etc...
|