Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Możesz użyć funkcji Async, aby uzyskać dostęp do plików. Za pomocą funkcji asynchronicznej można wywołać metody asynchroniczne bez używania wywołań zwrotnych lub dzielenia kodu między wiele metod lub wyrażeń lambda. Aby przekształcić kod synchroniczny na asynchroniczny, wystarczy wywołać metodę asynchroniczną zamiast synchronicznej i dodać do kodu kilka słów kluczowych.
Możesz rozważyć następujące przyczyny dodawania asynchronii do wywołań dostępu do plików:
Asynchrony sprawia, że aplikacje interfejsu użytkownika są bardziej dynamiczne, ponieważ wątek interfejsu użytkownika uruchamiający operację może wykonywać inne zadania. Jeśli wątek UI musi wykonywać kod, który zajmuje dużo czasu (na przykład ponad 50 milisekund), interfejs użytkownika może zamrozić się do momentu zakończenia operacji we/wy, a wątek UI może ponownie przetwarzać dane wejściowe z klawiatury i myszy oraz inne zdarzenia.
Asynchronia zwiększa skalowalność ASP.NET i innych aplikacji opartych na serwerze, zmniejszając zapotrzebowanie na wątki. Jeśli aplikacja używa dedykowanego wątku na odpowiedź, a tysiąc żądań jest obsługiwanych jednocześnie, potrzebne są tysiące wątków. Operacje asynchroniczne często nie muszą używać wątku podczas oczekiwania. Używają istniejącego wątku uzupełniania we/wy na krótko pod koniec.
Opóźnienie operacji dostępu do pliku może być bardzo niskie w bieżących warunkach, ale opóźnienie może znacznie wzrosnąć w przyszłości. Na przykład plik może zostać przeniesiony na serwer, który znajduje się na całym świecie.
Dodatkowe obciążenie związane z używaniem funkcji Async jest niewielkie.
Zadania asynchroniczne można łatwo uruchamiać równolegle.
Uruchamianie przykładów
Aby uruchomić przykłady w tym temacie, możesz utworzyć aplikację WPF lub aplikację Windows Forms, a następnie dodać przycisk. W zdarzeniu przycisku Click dodaj wywołanie pierwszej metody w każdym przykładzie.
W poniższych przykładach uwzględnij następujące Imports instrukcje.
Imports System
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.IO
Imports System.Text
Imports System.Threading.Tasks
Korzystanie z klasy FileStream
W przykładach w tym temacie użyto FileStream klasy , która ma opcję powodującą asynchroniczne operacje we/wy na poziomie systemu operacyjnego. Korzystając z tej opcji, można uniknąć blokowania wątku ThreadPool w wielu przypadkach. Aby włączyć tę opcję, należy określić argument useAsync=true lub options=FileOptions.Asynchronous w wywołaniu konstruktora.
Nie można użyć tej opcji z opcją StreamReader i StreamWriter jeśli otworzysz je bezpośrednio, określając ścieżkę pliku. Można jednak użyć tej opcji, jeśli dostarczysz im Stream, które otworzyła klasa FileStream. Należy pamiętać, że wywołania asynchroniczne są szybsze w aplikacjach interfejsu użytkownika, nawet jeśli wątek ThreadPool jest zablokowany, ponieważ wątek interfejsu użytkownika nie jest blokowany podczas oczekiwania.
Pisanie tekstu
Poniższy przykład zapisuje tekst w pliku. W każdej instrukcji await metoda natychmiast kończy działanie. Po zakończeniu operacji we/wy pliku metoda zostanie wznowiona od instrukcji następującej po instrukcji await. Należy pamiętać, że modyfikator asynchroniczny znajduje się w definicji metod korzystających z instrukcji 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
Oryginalny przykład zawiera instrukcję Await sourceStream.WriteAsync(encodedText, 0, encodedText.Length), która jest skurczem następujących dwóch instrukcji:
Dim theTask As Task = sourceStream.WriteAsync(encodedText, 0, encodedText.Length)
Await theTask
Pierwsza instrukcja zwraca zadanie i powoduje uruchomienie przetwarzania plików. Druga instrukcja z funkcją await powoduje natychmiastowe zakończenie metody i zwrócenie innego zadania. Po zakończeniu przetwarzania pliku wykonanie powraca do instrukcji, która następuje po await. Aby uzyskać więcej informacji, zobacz Przepływ sterowania w programach asynchronicznych (Visual Basic).
Odczytywanie tekstu
Poniższy przykład odczytuje tekst z pliku. Tekst jest buforowany i w tym wypadku umieszczany w obiekcie StringBuilder. W przeciwieństwie do poprzedniego przykładu ocena oczekiwania generuje wartość. Metoda ReadAsync zwraca Task<Int32>, więc wywołanie await generuje wartość Int32 (numRead) po zakończeniu operacji. Aby uzyskać więcej informacji, zobacz 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
Równoległe asynchroniczne I/O
W poniższym przykładzie pokazano przetwarzanie równoległe przez zapisanie 10 plików tekstowych. Dla każdego pliku WriteAsync metoda zwraca zadanie, które jest następnie dodawane do listy zadań. Instrukcja Await Task.WhenAll(tasks) kończy działanie metody i wznawia działanie metody po zakończeniu przetwarzania plików dla wszystkich zadań.
Przykład zamyka wszystkie wystąpienia FileStream w bloku Finally po zakończeniu zadań. Jeśli każda FileStream byłaby utworzona w instrukcji Imports, FileStream mógłby zostać zlikwidowany przed ukończeniem zadania.
Należy pamiętać, że każdy wzrost wydajności jest prawie całkowicie z przetwarzania równoległego, a nie z przetwarzania asynchronicznego. Zalety asynchronii to fakt, że nie obciąża ona wielu wątków ani wątku interfejsu użytkownika.
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
W przypadku korzystania z metod WriteAsync i ReadAsync, można określić element CancellationToken, którego można użyć do anulowania operacji w trakcie działania. Aby uzyskać więcej informacji, zobacz Fine-Tuning Aplikacja asynchroniczna (Visual Basic) i Anulowanie operacji w zarządzanych wątkach.