Använda Async för filåtkomst (Visual Basic)
Du kan använda funktionen Async för att komma åt filer. Med hjälp av funktionen Async kan du anropa till asynkrona metoder utan att använda motringningar eller dela upp koden mellan flera metoder eller lambda-uttryck. Om du vill göra synkron kod asynkron anropar du bara en asynkron metod i stället för en synkron metod och lägger till några nyckelord i koden.
Du kan överväga följande orsaker till att lägga till asynkront i filåtkomstanrop:
Asynkron gör UI-program mer dynamiska eftersom användargränssnittstråden som startar åtgärden kan utföra annat arbete. Om användargränssnittstråden måste köra kod som tar lång tid (till exempel mer än 50 millisekunder) kan användargränssnittet frysas tills I/O har slutförts och användargränssnittstråden kan bearbeta tangentbords- och musindata och andra händelser igen.
Asynkron förbättrar skalbarheten för ASP.NET och andra serverbaserade program genom att minska behovet av trådar. Om programmet använder en dedikerad tråd per svar och tusen begäranden hanteras samtidigt behövs tusen trådar. Asynkrona åtgärder behöver ofta inte använda en tråd under väntan. De använder den befintliga I/O-slutförandetråden en kort stund i slutet.
Svarstiden för en filåtkomståtgärd kan vara mycket låg under aktuella förhållanden, men svarstiden kan öka avsevärt i framtiden. En fil kan till exempel flyttas till en server som finns över hela världen.
Den extra kostnaden för att använda Async-funktionen är liten.
Asynkrona uppgifter kan enkelt köras parallellt.
Köra exemplen
Om du vill köra exemplen i det här avsnittet kan du skapa ett WPF-program eller ett Windows Forms-program och sedan lägga till en knapp. I knappens Click
händelse lägger du till ett anrop till den första metoden i varje exempel.
I följande exempel inkluderar du följande Imports
instruktioner.
Imports System
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.IO
Imports System.Text
Imports System.Threading.Tasks
Användning av FileStream-klassen
Exemplen FileStream i det här avsnittet använder klassen, som har ett alternativ som gör att asynkron I/O inträffar på operativsystemnivå. Med det här alternativet kan du undvika att blockera en ThreadPool-tråd i många fall. Om du vill aktivera det här alternativet anger useAsync=true
du argumentet eller options=FileOptions.Asynchronous
i konstruktoranropet.
Du kan inte använda det här alternativet med StreamReader och StreamWriter om du öppnar dem direkt genom att ange en filsökväg. Du kan dock använda det här alternativet om du anger ett Stream som FileStream klassen öppnade. Observera att asynkrona anrop går snabbare i användargränssnittsappar även om en ThreadPool-tråd blockeras, eftersom användargränssnittstråden inte blockeras under väntetiden.
Skriva text
I följande exempel skrivs text till en fil. Vid varje await-instruktion avslutas metoden omedelbart. När fil-I/O är klar återupptas metoden vid instruktionen som följer inväntningsuttryck. Observera att asynkron modifieraren finns i definitionen av metoder som använder await-instruktionen.
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
Det ursprungliga exemplet har -instruktionen Await sourceStream.WriteAsync(encodedText, 0, encodedText.Length)
, som är en kontraktion av följande två instruktioner:
Dim theTask As Task = sourceStream.WriteAsync(encodedText, 0, encodedText.Length)
Await theTask
Den första instruktionen returnerar en uppgift och gör att filbearbetningen startar. Den andra instruktionen med await gör att metoden omedelbart avslutas och returnerar en annan aktivitet. När filbearbetningen senare slutförs återgår körningen till -instruktionen som följer på inväntningen. Mer information finns i Kontrollera flöde i Async-program (Visual Basic).
Läsa text
I följande exempel läss text från en fil. Texten buffras och placeras i det här fallet i en StringBuilder. Till skillnad från i föregående exempel genererar utvärderingen av await ett värde. Metoden ReadAsync returnerar en Task<>Int32, så utvärderingen av await genererar ett Int32
värde (numRead
) när åtgärden har slutförts. Mer information finns i Async Return Types (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
Parallell asynkron I/O
I följande exempel visas parallell bearbetning genom att skriva 10 textfiler. För varje fil WriteAsync returnerar metoden en uppgift som sedan läggs till i en lista över aktiviteter. - Await Task.WhenAll(tasks)
instruktionen avslutar metoden och återupptas inom metoden när filbearbetningen är klar för alla aktiviteter.
Exemplet stänger alla FileStream instanser i ett Finally
block när uppgifterna har slutförts. Om var och FileStream
en i stället har skapats i en Imports
-instruktion kan den FileStream
tas bort innan aktiviteten har slutförts.
Observera att alla prestandaökningar nästan helt beror på parallell bearbetning och inte på asynkron bearbetning. Fördelarna med asynkron är att den inte binder upp flera trådar och att den inte binder upp användargränssnittstråden.
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
När du använder WriteAsync metoderna och ReadAsync kan du ange en CancellationToken, som du kan använda för att avbryta åtgärden mitt i strömmen. Mer information finns i Finjustera ditt Async-program (Visual Basic) och Annullering i hanterade trådar.