La meilleure solution consiste à implémenter une écriture asynchrone avec double tampon.
Regardez la chronologie:
------------------------------------------------>
FF|WWWWWWWW|FF|WWWWWWWW|FF|WWWWWWWW|FF|WWWWWWWW|
Le «F» représente le temps de remplissage du tampon et le «W» représente le temps d'écriture du tampon sur le disque. Donc, le problème de perdre du temps entre l'écriture de tampons dans un fichier. Cependant, en implémentant l'écriture sur un thread séparé, vous pouvez commencer à remplir immédiatement le tampon suivant comme ceci:
------------------------------------------------> (main thread, fills buffers)
FF|ff______|FF______|ff______|________|
------------------------------------------------> (writer thread)
|WWWWWWWW|wwwwwwww|WWWWWWWW|wwwwwwww|
F - remplissage du premier tampon
f - remplissage du deuxième tampon
W - écriture du premier tampon dans le fichier
w - écriture du deuxième tampon dans le fichier
_ - attendez la fin de l'opération
Cette approche avec des échanges de tampons est très utile lorsque le remplissage d'un tampon nécessite un calcul plus complexe (donc plus de temps). J'implémente toujours une classe CSequentialStreamWriter qui cache l'écriture asynchrone à l'intérieur, donc pour l'utilisateur final, l'interface n'a que des fonctions d'écriture.
Et la taille du tampon doit être un multiple de la taille du cluster de disques. Sinon, vous obtiendrez de mauvaises performances en écrivant un seul tampon dans 2 clusters de disques adjacents.
Écriture du dernier tampon.
Lorsque vous appelez la fonction Write pour la dernière fois, vous devez vous assurer que le tampon en cours de remplissage doit également être écrit sur le disque. Ainsi, CSequentialStreamWriter devrait avoir une méthode distincte, disons Finalize (final buffer flush), qui devrait écrire sur le disque la dernière partie des données.
La gestion des erreurs.
Alors que le code commence à remplir le deuxième tampon et que le premier est écrit sur un thread séparé, mais que l'écriture échoue pour une raison quelconque, le thread principal doit être conscient de cet échec.
------------------------------------------------> (main thread, fills buffers)
FF|fX|
------------------------------------------------> (writer thread)
__|X|
Supposons que l'interface d'un CSequentialStreamWriter a une fonction Write renvoie bool ou lève une exception, ayant ainsi une erreur sur un thread séparé, vous devez vous souvenir de cet état, donc la prochaine fois que vous appellerez Write ou Finilize sur le thread principal, la méthode retournera Faux ou lèvera une exception. Et peu importe à quel moment vous avez cessé de remplir un tampon, même si vous avez écrit des données à l'avance après l'échec - le fichier sera probablement corrompu et inutile.