Share via


Async gebruiken voor Bestandstoegang (Visual Basic)

U kunt de functie Async gebruiken om toegang te krijgen tot bestanden. Met behulp van de functie Async kunt u asynchrone methoden aanroepen zonder callbacks te gebruiken of uw code over meerdere methoden of lambda-expressies te splitsen. Als u synchrone code asynchroon wilt maken, roept u een asynchrone methode aan in plaats van een synchrone methode en voegt u enkele trefwoorden toe aan de code.

U kunt de volgende redenen overwegen om asynchroon toe te voegen aan aan aanroepen voor bestandstoegang:

  • Asynchrony maakt UI-toepassingen responsiefer omdat de UI-thread waarmee de bewerking wordt gestart, ander werk kan uitvoeren. Als de UI-thread code moet uitvoeren die lang duurt (bijvoorbeeld meer dan 50 milliseconden), kan de gebruikersinterface blokkeren totdat de I/O is voltooid en kan de UI-thread opnieuw toetsenbord- en muisinvoer en andere gebeurtenissen verwerken.

  • Asynchroon verbetert de schaalbaarheid van ASP.NET en andere servertoepassingen door de noodzaak van threads te verminderen. Als de toepassing een toegewezen thread per antwoord gebruikt en duizend aanvragen tegelijkertijd worden verwerkt, zijn er duizend threads nodig. Asynchrone bewerkingen hoeven vaak geen thread te gebruiken tijdens de wachttijd. Ze gebruiken de bestaande I/O-voltooiingsthread kort aan het einde.

  • De latentie van een bestandstoegangsbewerking kan erg laag zijn onder de huidige omstandigheden, maar de latentie kan in de toekomst aanzienlijk toenemen. Een bestand kan bijvoorbeeld worden verplaatst naar een server die zich over de hele wereld bevindt.

  • De extra overhead voor het gebruik van de Async-functie is klein.

  • Asynchrone taken kunnen eenvoudig parallel worden uitgevoerd.

De voorbeelden uitvoeren

Als u de voorbeelden in dit onderwerp wilt uitvoeren, kunt u een WPF-toepassing of een Windows Forms-toepassing maken en vervolgens een knop toevoegen. Voeg in de gebeurtenis van Click de knop een aanroep toe aan de eerste methode in elk voorbeeld.

Neem in de volgende voorbeelden de volgende Imports instructies op.

Imports System  
Imports System.Collections.Generic  
Imports System.Diagnostics  
Imports System.IO  
Imports System.Text  
Imports System.Threading.Tasks  

Gebruik van de FileStream-klasse

In de voorbeelden in dit onderwerp wordt de FileStream klasse gebruikt, die een optie heeft die ervoor zorgt dat asynchrone I/O op besturingssysteemniveau plaatsvindt. Met deze optie kunt u voorkomen dat een ThreadPool-thread in veel gevallen wordt geblokkeerd. Als u deze optie wilt inschakelen, geeft u het useAsync=true of options=FileOptions.Asynchronous argument op in de constructor-aanroep.

U kunt deze optie niet gebruiken en StreamReaderStreamWriter als u ze rechtstreeks opent door een bestandspad op te geven. U kunt deze optie echter gebruiken als u deze Stream opgeeft dat de klasse is FileStream geopend. Houd er rekening mee dat asynchrone aanroepen sneller zijn in UI-apps, zelfs als een ThreadPool-thread is geblokkeerd, omdat de UI-thread niet wordt geblokkeerd tijdens de wachttijd.

Tekst schrijven

In het volgende voorbeeld wordt tekst naar een bestand geschreven. Bij elke await-instructie wordt de methode onmiddellijk afgesloten. Wanneer de bestands-I/O is voltooid, wordt de methode hervat bij de instructie die volgt op de await-instructie. Houd er rekening mee dat de asynchrone wijzigingsfunctie de definitie bevat van methoden die gebruikmaken van de await-instructie.

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  

Het oorspronkelijke voorbeeld heeft de instructie Await sourceStream.WriteAsync(encodedText, 0, encodedText.Length), een samentrekking van de volgende twee instructies:

Dim theTask As Task = sourceStream.WriteAsync(encodedText, 0, encodedText.Length)  
Await theTask  

De eerste instructie retourneert een taak en zorgt ervoor dat bestandsverwerking wordt gestart. De tweede instructie met de wacht zorgt ervoor dat de methode onmiddellijk wordt afgesloten en een andere taak wordt geretourneerd. Wanneer de bestandsverwerking later is voltooid, keert de uitvoering terug naar de instructie die volgt op de wacht. Zie Controlestroom in Async-programma's (Visual Basic) voor meer informatie.

Tekst lezen

In het volgende voorbeeld wordt tekst uit een bestand gelezen. De tekst wordt gebufferd en in dit geval in een StringBuilder. In tegenstelling tot in het vorige voorbeeld produceert de evaluatie van de wacht een waarde. De ReadAsync methode retourneert eenInt32<>Task , zodat de evaluatie van de wacht een Int32 waarde (numRead) produceert nadat de bewerking is voltooid. Zie Asynchrone retourtypen (Visual Basic) voor meer informatie.

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  

Parallelle Asynchrone I/O

In het volgende voorbeeld ziet u parallelle verwerking door 10 tekstbestanden te schrijven. Voor elk bestand retourneert de WriteAsync methode een taak die vervolgens wordt toegevoegd aan een lijst met taken. De Await Task.WhenAll(tasks) instructie sluit de methode af en hervat binnen de methode wanneer bestandsverwerking is voltooid voor alle taken.

In het voorbeeld worden alle FileStream exemplaren in een Finally blok gesloten nadat de taken zijn voltooid. Als elk FileStream in plaats daarvan in een Imports instructie is gemaakt, kan het FileStream worden verwijderd voordat de taak is voltooid.

Houd er rekening mee dat een prestatieverbeteringen bijna volledig afkomstig zijn van de parallelle verwerking en niet van de asynchrone verwerking. De voordelen van asynchroon zijn dat het geen meerdere threads koppelt en dat de gebruikersinterfacethread niet wordt gekoppeld.

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  

Wanneer u de WriteAsync en ReadAsync methoden gebruikt, kunt u een CancellationToken, die u kunt gebruiken om de bewerking mid-stream te annuleren opgeven. Zie Uw asynchrone toepassing (Visual Basic) en annulering in Beheerde threads verfijnen voor meer informatie.

Zie ook