Лучшее решение - реализовать асинхронную запись с двойной буферизацией.
Посмотрите на временную шкалу:
------------------------------------------------>
FF|WWWWWWWW|FF|WWWWWWWW|FF|WWWWWWWW|FF|WWWWWWWW|
«F» представляет время для заполнения буфера, а «W» представляет время для записи буфера на диск. Так что проблема в том, чтобы тратить время между записью буферов в файл. Однако, реализовав запись в отдельном потоке, вы можете сразу же начать заполнение следующего буфера следующим образом:
------------------------------------------------> (main thread, fills buffers)
FF|ff______|FF______|ff______|________|
------------------------------------------------> (writer thread)
|WWWWWWWW|wwwwwwww|WWWWWWWW|wwwwwwww|
F - заполнение 1-го буфера
f - заполнение 2-го буфера
W - запись 1-го буфера в файл
w - запись 2-го буфера в файл
_ - ожидание завершения операции
Этот подход с заменой буфера очень полезен, когда заполнение буфера требует более сложных вычислений (следовательно, больше времени). Я всегда реализую класс CSequentialStreamWriter, который скрывает асинхронную запись внутри, поэтому для конечного пользователя интерфейс имеет только функцию Write.
И размер буфера должен быть кратным размеру дискового кластера. В противном случае вы получите низкую производительность, записав один буфер в 2 смежных дисковых кластера.
Запись последнего буфера.
Когда вы в последний раз вызываете функцию Write, вы должны убедиться, что текущий буфер заполняется, и на диск также записывается. Таким образом, CSequentialStreamWriter должен иметь отдельный метод, скажем, Finalize (финальная очистка буфера), который должен записывать на диск последнюю часть данных.
Обработка ошибок.
Хотя код начинает заполнять 2-й буфер, а 1-й пишется в отдельном потоке, но по какой-то причине запись не удалась, основной поток должен знать об этом сбое.
------------------------------------------------> (main thread, fills buffers)
FF|fX|
------------------------------------------------> (writer thread)
__|X|
Давайте предположим, что интерфейс CSequentialStreamWriter имеет функцию Write, возвращает bool или выдает исключение, поэтому при наличии ошибки в отдельном потоке вы должны запомнить это состояние, поэтому в следующий раз, когда вы вызовете Write или Finilize в основном потоке, метод вернет Ложь или бросит исключение. И на самом деле не имеет значения, в какой момент вы перестали заполнять буфер, даже если вы записали некоторые данные после сбоя - скорее всего, файл будет поврежден и бесполезен.