Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Для доступа к файлам можно использовать функцию Async. С помощью функции Async можно вызывать асинхронные методы без использования обратных вызовов или разделения кода по нескольким методам или лямбда-выражениям. Чтобы сделать синхронный код асинхронным, просто вызовите асинхронный метод вместо синхронного метода и добавьте несколько ключевых слов в код.
Вы можете рассмотреть следующие причины добавления асинхронности в вызовы доступа к файлам:
Asynchrony повышает скорость реагирования приложений пользовательского интерфейса, так как поток пользовательского интерфейса, запускающий операцию, может выполнять другую работу. Если поток пользовательского интерфейса должен выполнять код, который занимает много времени (например, более 50 миллисекунд), пользовательский интерфейс может заморозить до завершения ввода-вывода, а поток пользовательского интерфейса может снова обрабатывать ввод клавиатуры и мыши и другие события.
Асинхронность повышает масштабируемость ASP.NET и других серверных приложений, уменьшая потребность в потоках. Если приложение использует выделенный поток для каждого ответа и тысячи запросов обрабатываются одновременно, требуются тысячи потоков. Асинхронные операции часто не требуют использования потока во время ожидания. Они используют существующий поток завершения ввода-вывода кратко в конце.
Задержка операции доступа к файлам может быть очень низкой в текущих условиях, но задержка может значительно увеличиться в будущем. Например, файл может быть перемещен на сервер, который находится по всему миру.
Дополнительные затраты на использование функции Async невелики.
Асинхронные задачи можно легко выполнять параллельно.
Запуск примеров
Чтобы выполнить примеры в этом разделе, можно создать приложение WPF или приложение Windows Forms , а затем добавить кнопку. В событии кнопки Click
добавьте вызов первого метода в каждом примере.
В следующих примерах включите следующие Imports
инструкции.
Imports System
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.IO
Imports System.Text
Imports System.Threading.Tasks
Использование класса FileStream
В примерах этого раздела используется FileStream класс, который имеет параметр, который приводит к возникновению асинхронного ввода-вывода на уровне операционной системы. С помощью этого параметра можно избежать блокировки потока ThreadPool во многих случаях. Чтобы включить этот параметр, необходимо указать аргумент useAsync=true
или options=FileOptions.Asynchronous
в вызове конструктора.
Этот параметр нельзя использовать с StreamReader и StreamWriter, если вы открываете их напрямую, указав путь к файлу. Однако этот параметр можно использовать, если предоставить им Stream, который был открыт классом FileStream. Обратите внимание, что асинхронные вызовы быстрее используются в приложениях пользовательского интерфейса, даже если поток ThreadPool заблокирован, так как поток пользовательского интерфейса не блокируется во время ожидания.
Написание текста
В следующем примере записывается текст в файл. В каждой инструкции await метод немедленно завершает работу. После завершения ввода-вывода файла метод возобновляется в инструкции, следующей за инструкцией await. Обратите внимание, что асинхронный модификатор находится в определении методов, использующих инструкцию 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
В исходном примере имеется выражение Await sourceStream.WriteAsync(encodedText, 0, encodedText.Length)
, которое является сокращением следующих двух операторов.
Dim theTask As Task = sourceStream.WriteAsync(encodedText, 0, encodedText.Length)
Await theTask
Первая инструкция возвращает задачу и приводит к началу обработки файлов. Вторая инструкция с await приводит к тому, что метод немедленно завершает работу и возвращает другую задачу. После завершения обработки файлов выполнение возвращается в инструкцию, которая следует за ожиданием. Дополнительные сведения см. в разделе "Поток управления" в асинхронных программах (Visual Basic).
Чтение текста
В следующем примере считывается текст из файла. Текст буферичен и, в данном случае, помещается в объект StringBuilder. В отличие от предыдущего примера, оценка await создает значение. Метод ReadAsync возвращает Task<Int32>, поэтому выполнение await приводит к тому, что выдается Int32
значение (numRead
) после завершения операции. Дополнительные сведения см. в статье 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
Параллельный асинхронный ввод-вывод
В следующем примере демонстрируется параллельная обработка путем записи 10 текстовых файлов. Для каждого файла WriteAsync метод возвращает задачу, которая затем добавляется в список задач. Оператор Await Task.WhenAll(tasks)
завершает метод и возобновляет работу в методе при завершении обработки файлов для всех задач.
Пример закрывает все FileStream инстанции в блоке Finally
после завершения задач. Если FileStream
был создан в операторе Imports
, FileStream
могло быть уничтожено до завершения задачи.
Обратите внимание, что любое повышение производительности почти полностью происходит от параллельной обработки, а не асинхронной обработки. Преимущества асинхронности заключается в том, что он не связывает несколько потоков, и что он не связывает поток пользовательского интерфейса.
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
При использовании WriteAsync и ReadAsync методов можно указать CancellationToken, который можно использовать для отмены операции в середине потока. Дополнительные сведения см. в Fine-Tuning Асинхронное приложение (Visual Basic) и Отмена в управляемых потоках.
См. также
- Асинхронное программирование с использованием ключевых слов Async и Await (Visual Basic)
- Async Return Types (Visual Basic) (Типы возвращаемых значений Async (Visual Basic))
- Поток управления в асинхронных программах (Visual Basic)