Solusi terbaik adalah dengan mengimplementasikan penulisan async dengan buffering ganda.
Lihatlah garis waktu:
------------------------------------------------>
FF|WWWWWWWW|FF|WWWWWWWW|FF|WWWWWWWW|FF|WWWWWWWW|
'F' mewakili waktu untuk mengisi buffer, dan 'W' mewakili waktu untuk menulis buffer ke disk. Jadi masalah dalam membuang waktu antara menulis buffer ke file. Namun, dengan menerapkan penulisan pada utas terpisah, Anda dapat mulai mengisi buffer berikutnya segera seperti ini:
------------------------------------------------> (main thread, fills buffers)
FF|ff______|FF______|ff______|________|
------------------------------------------------> (writer thread)
|WWWWWWWW|wwwwwwww|WWWWWWWW|wwwwwwww|
F - mengisi buffer 1
f - mengisi buffer 2
W - menulis buffer 1 ke file
w - menulis buffer 2 ke file
_ - menunggu sementara operasi selesai
Pendekatan ini dengan swap swap sangat berguna ketika mengisi buffer membutuhkan perhitungan yang lebih kompleks (karenanya, lebih banyak waktu). Saya selalu menerapkan kelas CSequentialStreamWriter yang menyembunyikan tulisan asinkron di dalamnya, jadi untuk pengguna akhir antarmuka baru saja menulis fungsi.
Dan ukuran buffer harus kelipatan dari ukuran cluster disk. Jika tidak, Anda akan berakhir dengan kinerja yang buruk dengan menulis buffer tunggal ke 2 kluster disk yang berdekatan.
Menulis buffer terakhir.
Ketika Anda memanggil fungsi Write untuk yang terakhir kali, Anda harus memastikan bahwa buffer saat ini sedang diisi harus ditulis ke disk juga. Jadi CSequentialStreamWriter harus memiliki metode terpisah, katakanlah Finalize (final buffer flush), yang harus menulis ke disk bagian terakhir dari data.
Menangani kesalahan.
Sementara kode mulai mengisi buffer ke-2, dan yang ke-1 sedang ditulis di utas terpisah, tetapi penulisan gagal karena beberapa alasan, utas utama harus menyadari kegagalan itu.
------------------------------------------------> (main thread, fills buffers)
FF|fX|
------------------------------------------------> (writer thread)
__|X|
Mari kita asumsikan antarmuka CSequentialStreamWriter memiliki fungsi Write mengembalikan bool atau melempar pengecualian, sehingga memiliki kesalahan pada utas terpisah, Anda harus mengingat keadaan itu, jadi lain kali Anda memanggil Tulis atau Finilize pada utas utama, metode tersebut akan kembali Salah atau akan melempar pengecualian. Dan tidak masalah pada titik mana Anda berhenti mengisi buffer, bahkan jika Anda menulis beberapa data di depan setelah kegagalan - kemungkinan besar file tersebut akan rusak dan tidak berguna.