Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Anda dapat menggunakan fitur asinkron untuk mengakses file. Dengan menggunakan fitur asinkron, Anda dapat memanggil metode asinkron tanpa menggunakan panggilan balik eksplisit atau memisahkan kode Anda secara manual di beberapa metode atau ekspresi lambda. Untuk membuat kode sinkron menjadi asinkron, Anda cukup memanggil metode asinkron alih-alih metode sinkron dan menambahkan beberapa kata kunci pada kode.
Anda dapat mempertimbangkan alasan berikut untuk menambahkan asinkron ke panggilan akses file:
- 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 dapat 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 akan utas. Jika aplikasi menggunakan utas khusus per respons dan seribu permintaan ditangani secara bersamaan, maka seribu utas akan diperlukan. Operasi asinkron sering kali tidak perlu menggunakan utas selama menunggu. Itu menggunakan utas penyelesaian I/O yang ada secara singkat di akhir.
- Latensi operasi akses file mungkin sangat rendah dalam kondisi saat ini, tetapi latensinya dapat meningkat pesat di masa mendatang. Misalnya, file dapat dipindahkan ke server yang ada di seluruh dunia.
- Overhead yang ditambahkan dari penggunaan fitur Asinkron berukuran kecil.
- Tugas asinkron dapat dengan mudah dijalankan secara paralel.
Menggunakan kelas yang sesuai
Contoh sederhana dalam topik ini menunjukkan File.WriteAllTextAsync dan File.ReadAllTextAsync. Untuk kontrol yang baik atas operasi I/O file, gunakan FileStream kelas , yang memiliki opsi yang menyebabkan I/O asinkron terjadi pada tingkat sistem operasi. Dengan menggunakan opsi ini, Anda dapat menghindari pemblokiran utas dari kumpulan utas dalam banyak kasus. Untuk mengaktifkan opsi ini, Anda menentukan 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 memberi mereka Stream yang dibuka oleh kelas FileStream. Panggilan asinkron lebih cepat di aplikasi UI meskipun utas kumpulan utas diblokir, karena utas UI tidak diblokir selama menunggu.
Menulis teks
Contoh berikut menulis teks ke file. Pada setiap pernyataan menunggu, metode akan segera keluar. Ketika I/O file selesai, metode dilanjutkan pada pernyataan yang mengikuti pernyataan menunggu. Pengubah asinkron berada dalam definisi metode yang menggunakan pernyataan tunggu.
Contoh sederhana
public async Task SimpleWriteAsync()
{
string filePath = "simple.txt";
string text = $"Hello World";
await File.WriteAllTextAsync(filePath, text);
}
Contoh kontrol terbatas
public async Task ProcessWriteAsync()
{
string filePath = "temp.txt";
string text = $"Hello World{Environment.NewLine}";
await WriteTextAsync(filePath, text);
}
async Task WriteTextAsync(string filePath, string text)
{
byte[] encodedText = Encoding.Unicode.GetBytes(text);
using var sourceStream =
new FileStream(
filePath,
FileMode.Create, FileAccess.Write, FileShare.None,
bufferSize: 4096, useAsync: true);
await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
}
Contoh asli memiliki pernyataan await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
, yang merupakan kontraksi dari dua pernyataan berikut:
Task theTask = sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
await theTask;
Pernyataan pertama menampilkan tugas dan menyebabkan pemrosesan file dimulai. Pernyataan kedua dengan menantikan menyebabkan metode segera keluar dan menampilkan tugas yang berbeda. Ketika pemrosesan file nanti selesai, eksekusi kembali ke pernyataan yang mengikuti menunggu.
Membaca teks
Contoh berikut membaca teks dari file.
Contoh sederhana
public async Task SimpleReadAsync()
{
string filePath = "simple.txt";
string text = await File.ReadAllTextAsync(filePath);
Console.WriteLine(text);
}
Contoh kontrol terbatas
Teks di-buffer dan, dalam hal ini, ditempatkan ke dalam StringBuilder. Tidak seperti dalam contoh sebelumnya, evaluasi menunggu menghasilkan nilai. Metode ReadAsync mengembalikanTask<Int32>, sehingga evaluasi menunggu menghasilkan Int32
nilai numRead
setelah operasi selesai. Untuk informasi selengkapnya, lihat Jenis Pengembalian Asinkron (C#).
public async Task ProcessReadAsync()
{
try
{
string filePath = "temp.txt";
if (File.Exists(filePath) != false)
{
string text = await ReadTextAsync(filePath);
Console.WriteLine(text);
}
else
{
Console.WriteLine($"file not found: {filePath}");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
async Task<string> ReadTextAsync(string filePath)
{
using var sourceStream =
new FileStream(
filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true);
var sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
I/O asinkron paralel
Contoh berikut menunjukkan pemrosesan paralel dengan menulis 10 file teks.
Contoh sederhana
public async Task SimpleParallelWriteAsync()
{
string folder = Directory.CreateDirectory("tempfolder").Name;
IList<Task> writeTaskList = new List<Task>();
for (int index = 11; index <= 20; ++ index)
{
string fileName = $"file-{index:00}.txt";
string filePath = $"{folder}/{fileName}";
string text = $"In file {index}{Environment.NewLine}";
writeTaskList.Add(File.WriteAllTextAsync(filePath, text));
}
await Task.WhenAll(writeTaskList);
}
Contoh kontrol terbatas
Untuk setiap file, metode WriteAsync mengembalikan tugas yang kemudian ditambahkan ke daftar tugas. Pernyataan await Task.WhenAll(tasks);
keluar dari metode dan melanjutkan dalam metode ketika pemrosesan file selesai untuk semua tugas.
Contoh tersebut menutup semua instans FileStream dalam blok finally
setelah tugas selesai. Jika masing-masing FileStream
dibuat dalam pernyataan using
, maka FileStream
mungkin dibuang sebelum tugas selesai.
Setiap peningkatan performa hampir seluruhnya berasal dari pemrosesan paralel dan bukan pemrosesan asinkron. Keuntungan dari asinkron adalah tidak mengikat beberapa utas dan tidak mengikat utas antarmuka pengguna.
public async Task ProcessMultipleWritesAsync()
{
IList<FileStream> sourceStreams = new List<FileStream>();
try
{
string folder = Directory.CreateDirectory("tempfolder").Name;
IList<Task> writeTaskList = new List<Task>();
for (int index = 1; index <= 10; ++ index)
{
string fileName = $"file-{index:00}.txt";
string filePath = $"{folder}/{fileName}";
string text = $"In file {index}{Environment.NewLine}";
byte[] encodedText = Encoding.Unicode.GetBytes(text);
var sourceStream =
new FileStream(
filePath,
FileMode.Create, FileAccess.Write, FileShare.None,
bufferSize: 4096, useAsync: true);
Task writeTask = sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
sourceStreams.Add(sourceStream);
writeTaskList.Add(writeTask);
}
await Task.WhenAll(writeTaskList);
}
finally
{
foreach (FileStream sourceStream in sourceStreams)
{
sourceStream.Close();
}
}
}
Saat menggunakan metode WriteAsync dan ReadAsync, Anda dapat menentukan CancellationToken yang dapat Anda gunakan untuk membatalkan operasi mid-stream. Untuk informasi selengkapnya, lihat Pembatalan di utas terkelola .