La soluzione migliore è implementare una scrittura asincrona con doppio buffering.
Guarda la linea del tempo:
------------------------------------------------>
FF|WWWWWWWW|FF|WWWWWWWW|FF|WWWWWWWW|FF|WWWWWWWW|
La 'F' rappresenta il tempo per il riempimento del buffer e 'W' rappresenta il tempo per la scrittura del buffer su disco. Quindi il problema nello sprecare tempo tra la scrittura di buffer su file. Tuttavia, implementando la scrittura su un thread separato, puoi iniziare subito a riempire il buffer successivo in questo modo:
------------------------------------------------> (main thread, fills buffers)
FF|ff______|FF______|ff______|________|
------------------------------------------------> (writer thread)
|WWWWWWWW|wwwwwwww|WWWWWWWW|wwwwwwww|
F - riempimento 1 ° buffer
f - riempimento 2 ° buffer
W - scrittura del 1 ° buffer nel file
w - scrittura del 2 ° buffer nel file
_ - attendere il completamento dell'operazione
Questo approccio con buffer swap è molto utile quando si riempie un buffer richiede un calcolo più complesso (quindi, più tempo). Implemento sempre una classe CSequentialStreamWriter che nasconde la scrittura asincrona all'interno, quindi per l'utente finale l'interfaccia ha solo funzioni di scrittura.
E la dimensione del buffer deve essere un multiplo della dimensione del cluster di dischi. Altrimenti, si finiranno con scarse prestazioni scrivendo un singolo buffer su 2 cluster di dischi adiacenti.
Scrivere l'ultimo buffer.
Quando si chiama la funzione Write per l'ultima volta, è necessario assicurarsi che anche il buffer corrente in fase di compilazione debba essere scritto sul disco. Pertanto CSequentialStreamWriter dovrebbe avere un metodo separato, diciamo Finalize (final buffer flush), che dovrebbe scrivere sul disco l'ultima porzione di dati.
Gestione degli errori.
Mentre il codice inizia a riempire il secondo buffer e il primo viene scritto su un thread separato, ma la scrittura non riesce per qualche motivo, il thread principale dovrebbe essere consapevole di tale errore.
------------------------------------------------> (main thread, fills buffers)
FF|fX|
------------------------------------------------> (writer thread)
__|X|
Supponiamo che l'interfaccia di CSequentialStreamWriter abbia la funzione Write che ritorni a bool o generi un'eccezione, quindi avendo un errore su un thread separato, devi ricordare quello stato, quindi la prossima volta che chiami Write o Finilize sul thread principale, il metodo restituirà Falso o genererà un'eccezione. E non importa davvero a che punto hai smesso di riempire un buffer, anche se hai scritto alcuni dati in anticipo dopo l'errore - molto probabilmente il file sarebbe danneggiato e inutile.