Menggunakan Asinkron untuk Akses File (Visual Basic)

Gunakan fitur Asinkron untuk mengakses file. Dengan menggunakan fitur Asinkron, Anda dapat memanggil metode asinkron tanpa menggunakan panggilan balik atau membagi kode Anda di beberapa metode atau ekspresi lambda. Untuk mengubah kode sinkron menjadi asinkron, panggil metode asinkron sebagai pengganti metode sinkron, dan tambahkan beberapa kata kunci khusus asinkron ke dalam kode.

Pertimbangkan untuk menambahkan asinkron ke panggilan akses file karena alasan berikut:

  • Asinkron membuat aplikasi UI lebih responsif karena utas UI yang meluncurkan operasi dapat melakukan pekerjaan lain. Jika utas UI harus menjalankan kode yang membutuhkan waktu lama (misalnya, lebih dari 50 milidetik), UI mungkin membeku hingga I/O selesai dan utas UI dapat kembali memproses input keyboard dan mouse dan peristiwa lainnya.

  • Asinkron meningkatkan skalabilitas ASP.NET dan aplikasi berbasis server lainnya dengan mengurangi kebutuhan penggunaan utas. Jika aplikasi menggunakan utas khusus per respons dan seribu permintaan ditangani secara bersamaan, seribu utas diperlukan. Operasi asinkron sering kali tidak perlu menggunakan utas selama penantian. Mereka menggunakan utas penyelesaian I/O yang sudah ada dengan singkat di bagian akhir.

  • Latensi operasi akses file mungkin sangat rendah dalam kondisi saat ini, tetapi latensinya mungkin sangat meningkat di masa depan. Misalnya, file mungkin dipindahkan ke server yang ada di seluruh dunia.

  • Overhead tambahan dari penggunaan fitur Asinkron adalah kecil.

  • Beberapa operasi I/O asinkron dapat berjalan tanpa memblokir utas panggilan.

Jalankan contoh

Untuk menjalankan contoh dalam topik ini, buat Aplikasi WPF atau Aplikasi Formulir Windows lalu tambahkan Tombol. Dalam peristiwa tombol Click , tambahkan panggilan ke metode pertama di setiap contoh.

Dalam contoh berikut, sertakan pernyataan berikut Imports .

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

Penggunaan kelas FileStream

Contoh dalam topik ini menggunakan FileStream kelas , yang memiliki opsi yang menyebabkan I/O asinkron terjadi pada tingkat sistem operasi. Dengan menggunakan opsi ini, Anda dapat menghindari pemblokiran thread pada ThreadPool dalam banyak kasus. Untuk mengaktifkan opsi ini, tentukan argumen useAsync=true atau options=FileOptions.Asynchronous dalam panggilan konstruktor.

Anda tidak dapat menggunakan opsi ini dengan StreamReader dan StreamWriter jika Anda membukanya secara langsung dengan menentukan jalur file. Namun, Anda dapat menggunakan opsi ini jika Anda memberikan mereka Stream yang dibuka oleh kelas FileStream. Panggilan asinkron lebih cepat di aplikasi UI meskipun utas ThreadPool diblokir, karena utas UI tidak diblokir selama penantian.

Menulis teks

Contoh berikut menulis teks ke file. Pada setiap pernyataan 'await', metode segera berhenti sementara. Ketika I/O file selesai, metode dilanjutkan pada pernyataan yang mengikuti pernyataan tunggu. Pengubah asinkron berada dalam definisi metode yang menggunakan pernyataan tunggu.

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

Contoh asli memiliki pernyataan Await sourceStream.WriteAsync(encodedText, 0, encodedText.Length), yang merupakan kontraksi dari dua pernyataan berikut:

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

Pernyataan pertama mengembalikan tugas dan menyebabkan pemrosesan file dimulai. Pernyataan kedua dengan menunggu menyebabkan metode segera keluar dan mengembalikan tugas yang berbeda. Ketika pemrosesan file nanti selesai, eksekusi kembali ke pernyataan yang mengikuti await. Untuk informasi selengkapnya, lihat Alur Kontrol di Program Asinkron (Visual Basic).

Membaca teks

Contoh berikut membaca teks dari file. Teks di-buffer dan, dalam hal ini, ditempatkan ke dalam StringBuilder. Tidak seperti dalam contoh sebelumnya, evaluasi menunggu menghasilkan nilai. Metode ReadAsync mengembalikan Task<Int32>, sehingga evaluasi dari await menghasilkan nilai Int32 (numRead) setelah operasi selesai. Untuk informasi selengkapnya, lihat Jenis Pengembalian Asinkron (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

Beberapa operasi I/O asinkron

Contoh berikut memulai beberapa operasi penulisan asinkron. Runtime mengantrekan operasi ini, dan implementasi yang mendasarinya mungkin menggunakan I/O asinkron sistem operasi (OS) atau utas kumpulan utas tergantung pada platform dan konfigurasi, sehingga konkurensi aktual tergantung pada OS dan perangkat keras. Untuk setiap file, metode WriteAsync tersebut mengembalikan tugas yang ditambahkan ke dalam daftar tugas. Pernyataan Await Task.WhenAll(tasks) keluar dari metode dan melanjutkan dalam metode ketika pemrosesan file selesai untuk semua tugas.

Contoh menutup semua instans FileStream dalam blok Finally setelah tugas selesai. Jika masing-masing FileStream dibuat dalam pernyataan Using, FileStream mungkin akan dibuang sebelum tugas selesai.

Pendekatan asinkron menghindari pemblokiran utas panggilan saat I/O tertunda. Dalam banyak kasus, peningkatan throughput tergantung pada OS, perangkat keras, dan, pada beberapa platform, perilaku runtime .NET seperti batas kumpulan utas dan penjadwalan.

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

Saat menggunakan metode WriteAsync dan ReadAsync, Anda dapat menentukan CancellationToken untuk membatalkan operasi di tengah proses. Untuk informasi lebih lanjut, lihat Fine-Tuning Aplikasi Asinkron Anda (Visual Basic) dan Pembatalan pada Thread Terkelola.

Lihat juga