Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
È possibile usare la funzionalità asincrona per accedere ai file. Usando la funzionalità asincrona, è possibile chiamare metodi asincroni senza usare callback o suddividere il codice tra più metodi o espressioni lambda. Per rendere asincrono il codice sincrono, è sufficiente chiamare un metodo asincrono anziché un metodo sincrono e aggiungere alcune parole chiave al codice.
È possibile considerare i motivi seguenti per aggiungere asincronia alle chiamate di accesso ai file:
Asincronia rende le applicazioni dell'interfaccia utente più reattive perché il thread dell'interfaccia utente che avvia l'operazione può eseguire altre operazioni. Se il thread dell'interfaccia utente deve eseguire codice che richiede molto tempo (ad esempio, più di 50 millisecondi), l'interfaccia utente può bloccarsi fino al completamento dell'I/O e il thread dell'interfaccia utente può elaborare nuovamente l'input della tastiera e del mouse e altri eventi.
Asincronia migliora la scalabilità di ASP.NET e altre applicazioni basate su server riducendo la necessità di thread. Se l'applicazione usa un thread dedicato per risposta e vengono gestite contemporaneamente migliaia di richieste, sono necessari mille thread. Le operazioni asincrone spesso non devono usare un thread durante l'attesa. Usano brevemente, alla fine, il thread di completamento I/O esistente.
La latenza di un'operazione di accesso ai file potrebbe essere molto bassa in condizioni correnti, ma la latenza potrebbe aumentare notevolmente in futuro. Ad esempio, un file può essere spostato in un server di tutto il mondo.
Il sovraccarico derivante dall’uso della funzionalità asincrona è ridotto.
Le attività asincrone possono essere eseguite facilmente in parallelo.
Esecuzione degli esempi
Per eseguire gli esempi in questo argomento, è possibile creare un'applicazione WPF o un'applicazione Windows Form e quindi aggiungere un pulsante. Nell'evento Click del pulsante, aggiungere una chiamata al primo metodo in ogni esempio.
Negli esempi seguenti, includi le seguenti istruzioni Imports.
Imports System
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.IO
Imports System.Text
Imports System.Threading.Tasks
Uso della classe FileStream
Gli esempi in questo argomento usano la FileStream classe , che include un'opzione che causa l'esecuzione di I/O asincroni a livello di sistema operativo. Usando questa opzione, è possibile evitare di bloccare un thread ThreadPool in molti casi. Per abilitare questa opzione, specificare l'argomento useAsync=true o options=FileOptions.Asynchronous nella chiamata al costruttore.
Non è possibile usare questa opzione con StreamReader e StreamWriter se le si apre direttamente specificando un percorso di file. Tuttavia, è possibile usare questa opzione se si fornisce loro un Stream che la classe FileStream ha aperto. Si noti che le chiamate asincrone sono più veloci nelle app dell'interfaccia utente anche se un thread ThreadPool è bloccato, perché il thread dell'interfaccia utente non viene bloccato durante l'attesa.
Scrittura di testo
Nell'esempio seguente viene scritto testo in un file. A ogni istruzione 'await', il metodo esce immediatamente. Al termine dell'I/O del file, il metodo riprende in corrispondenza dell'istruzione che segue l'istruzione await. Si noti che il modificatore asincrono è nella definizione dei metodi che usano l'istruzione await.
Public Async Sub ProcessWrite()
Dim filePath = "temp2.txt"
Dim text = "Hello World" & ControlChars.CrLf
Await WriteTextAsync(filePath, text)
End Sub
Private Async Function WriteTextAsync(filePath As String, text As String) As Task
Dim encodedText As Byte() = Encoding.Unicode.GetBytes(text)
Using sourceStream As New FileStream(filePath,
FileMode.Append, FileAccess.Write, FileShare.None,
bufferSize:=4096, useAsync:=True)
Await sourceStream.WriteAsync(encodedText, 0, encodedText.Length)
End Using
End Function
L'esempio originale ha l'istruzione Await sourceStream.WriteAsync(encodedText, 0, encodedText.Length), ovvero una contrazione delle due istruzioni seguenti:
Dim theTask As Task = sourceStream.WriteAsync(encodedText, 0, encodedText.Length)
Await theTask
La prima istruzione restituisce un'attività e determina l'avvio dell'elaborazione di file. La seconda istruzione con await fa sì che il metodo esca immediatamente e restituisca un compito diverso. Al termine dell'elaborazione del file, l'esecuzione torna all'istruzione che segue l'await. Per altre informazioni, vedere Flusso di controllo in Programmi asincroni (Visual Basic).For more information, see Control Flow in Async Programs (Visual Basic).
Lettura del testo
Nell'esempio seguente viene letto testo da un file. Il testo viene memorizzato nel buffer e, in questo caso, inserito in un oggetto StringBuilder. A differenza dell'esempio precedente, la valutazione di await produce un valore. Il ReadAsync metodo restituisce un Task<Int32>, in modo che la valutazione di await produca un Int32 valore (numRead) al termine dell'operazione. Per altre informazioni, vedere Tipi restituiti asincroni (Visual Basic).
Public Async Sub ProcessRead()
Dim filePath = "temp2.txt"
If File.Exists(filePath) = False Then
Debug.WriteLine("file not found: " & filePath)
Else
Try
Dim text As String = Await ReadTextAsync(filePath)
Debug.WriteLine(text)
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try
End If
End Sub
Private Async Function ReadTextAsync(filePath As String) As Task(Of String)
Using sourceStream As New FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize:=4096, useAsync:=True)
Dim sb As New StringBuilder
Dim buffer As Byte() = New Byte(&H1000) {}
Dim numRead As Integer
numRead = Await sourceStream.ReadAsync(buffer, 0, buffer.Length)
While numRead <> 0
Dim text As String = Encoding.Unicode.GetString(buffer, 0, numRead)
sb.Append(text)
numRead = Await sourceStream.ReadAsync(buffer, 0, buffer.Length)
End While
Return sb.ToString
End Using
End Function
I/O asincrono parallelo
Nell'esempio seguente viene illustrata l'elaborazione parallela scrivendo 10 file di testo. Per ogni file, il WriteAsync metodo restituisce un'attività che viene quindi aggiunta a un elenco di attività. L'istruzione Await Task.WhenAll(tasks) esce dal metodo e riprende all'interno del metodo al termine dell'elaborazione dei file per tutte le attività.
L'esempio chiude tutte le FileStream istanze in un blocco Finally una volta completati i compiti. Se ogni FileStream fosse invece creato in una dichiarazione Imports, il FileStream potrebbe essere smaltito prima che il compito sia completato.
Si noti che qualsiasi miglioramento delle prestazioni è quasi interamente dall'elaborazione parallela e non dall'elaborazione asincrona. I vantaggi dell'asincronia sono che non collega più thread e che non collega il thread dell'interfaccia utente.
Public Async Sub ProcessWriteMult()
Dim folder = "tempfolder\"
Dim tasks As New List(Of Task)
Dim sourceStreams As New List(Of FileStream)
Try
For index = 1 To 10
Dim text = "In file " & index.ToString & ControlChars.CrLf
Dim fileName = "thefile" & index.ToString("00") & ".txt"
Dim filePath = folder & fileName
Dim encodedText As Byte() = Encoding.Unicode.GetBytes(text)
Dim sourceStream As New FileStream(filePath,
FileMode.Append, FileAccess.Write, FileShare.None,
bufferSize:=4096, useAsync:=True)
Dim theTask As Task = sourceStream.WriteAsync(encodedText, 0, encodedText.Length)
sourceStreams.Add(sourceStream)
tasks.Add(theTask)
Next
Await Task.WhenAll(tasks)
Finally
For Each sourceStream As FileStream In sourceStreams
sourceStream.Close()
Next
End Try
End Sub
Quando si utilizzano i metodi WriteAsync e ReadAsync, è possibile specificare un CancellationToken oggetto, che puoi usare per annullare l'operazione nel corso del processo. Per ulteriori informazioni, vedere Fine-Tuning La tua applicazione asincrona (Visual Basic) e Annullamento nei thread gestiti.